Javascript高级程序设计3笔记

摘要:
//新建对象对象person2person。name=“hank”;//4person.job=“吃”;//。。。5人。sayName=function(){//添加方法sayName6alert(this.name);function(){6alert(this.name);job){2varo=newObject();
 

完全是笔记,99.9%摘录自高程3,方便学习复习。

  • 对象认识
  • “类”
  • 原型
  • 继承
 

一、对象认识

最原始的创建对象方式:

 
1 var person = new Object(); //new一个Object对象 person
2 person.name = "hank"; //给person添加属性name,初值为hank
3 person.age = 28; //..
4 person.job = "eat"; //...
5 person.sayName = function(){ //给person添加方法sayName
6     alert(this.name);
7 }

看上去有点笨重,后来就流行字面量了:

1 var person{
2     name : "hank",
3     age : 28,
4     job : "eat",
5     sayName : function(){
6         alert(this.name);
7     }
8 }    

 

以上两种的缺点:如果创建很多对象,就会产生大量的重复代码。所以,开始有“类”的出现了。一个类,想要多少实例,自己new。

二、类(意义上的)

1.工厂模式

ECMAScript无法创建类。那么,就用一个函数将第一种封装起来。如此这般,可通过调用ceartPerson来创建多个相似对象。但是无法识别对象类型.

 1 function creatPerson(name,age,job){
 2     var o = new Object(); //new
 3     o.name = name; //添加属性
 4     o.age = age; //..
 5     o.job = job; //..
 6     o.sayName = function(){ //添加方法
 7         alert(this.name);
 8     }
 9     return o; //将new好的对象返回
10 }

2.构造函数模式

 1 function Person(name, age, job){
 2     //没有new对象
 3     this.name = name; //属性和方法赋值给this对象
 4     this.age = age;
 5     this.job = job;
 6     this.sayName = function(){
 7         alert(this.name);
 8     };
 9     //没有return
10 }
11 var person1 = new Person("Nicholas", 29, "Software Engineer");
12 var person2 = new Person("Greg", 27, "Doctor");    

 

person1和person2分别保存着Person的一个不同的实例。都有一个constructor(构造函数)属性,指向Person“person1.constructor == Person”。如此这般之后,就能instanceof出构造函数(对象类型)而不都是Object了。 
-调用方式

 1 // 当作构造函数使用
 2 var person = new Person("Nicholas", 29, "Software Engineer");
 3 person.sayName(); //"Nicholas"
 4 // 作为普通函数调用
 5 Person("Greg", 27, "Doctor"); // 添加到 window
 6 window.sayName(); //"Greg"
 7 // 在另一个对象的作用域中调用
 8 var o = new Object();
 9 Person.call(o, "Kristen", 25, "Nurse");// 添加到 o
10 o.sayName(); //"Kristen"

 

缺点:每个方法都要在每个实例上重新创建一遍。不同实例上的同名函数是不相等的,所以alert(person1.sayName == person2.sayName); //false。通过把函数定义转移到构造函数外部来解决这个问题

 1 function Person(name, age, job){
 2     this.name = name;
 3     this.age = age;
 4     this.job = job;
 5     this.sayName = sayName;
 6 }
 7 function sayName(){
 8     alert(this.name);
 9 }
10 var person1 = new Person("Nicholas", 29, "Software Engineer");
11 var person2 = new Person("Greg", 27, "Doctor");
12 alert(person1.sayName == person2.sayName); //true

 

可是新问题又来了:在全局作用域中定义的函数实际上只能被某个对象调用,这让全局作用域有点名不副实。而更让人无法接受的是:如果对象需要定义很多方法,那么就要定义很多个全局函数,于是我们这个自定义的引用类型就丝毫没有封装性可言了。好在,这些问题可以通过使用原型模式来解决。

三、原型

每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象。这个对象使得所有实例共享属性和方法。

 1 function Person(){
 2 }
 3 Person.prototype.name = "Nicholas";
 4 Person.prototype.age = 29;
 5 Person.prototype.job = "Software Engineer";
 6 Person.prototype.sayName = function(){
 7     alert(this.name);
 8 };
 9 var person1 = new Person();
10 person1.sayName(); //"Nicholas"
11 var person2 = new Person();
12 person2.sayName(); //"Nicholas"
13 alert(person1.sayName == person2.sayName); //true

 

和构造函数模式不同的是,实例共享属性方法。实例访问的实例和方法都是同一个。 
此处输入图片的描述

查找对象属性:在对象实体中找,找不到就到原型对象中找。能访问,但是不能修改。即,实例中添加同名属性后,只是在该实例中存在。

 
 1 function Person(){
 2 }
 3 Person.prototype.name = "Nicholas";
 4 Person.prototype.age = 29;
 5 Person.prototype.job = "Software Engineer";
 6 Person.prototype.sayName = function(){
 7     alert(this.name);
 8 };
 9 var person1 = new Person();
10 var person2 = new Person();
11 person1.name = "Greg";
12 alert(person1.name); //"Greg" ——来自实例
13 alert(person2.name); //"Nicholas" ——来自原型
14 delete person1.name;
15 alert(person1.name); //"Nicholas"——来自原型

 

使用 hasOwnProperty() 方法可以检测一个属性是存在于实例中,还是存在于原型中.只在给定属性存在于对象实例中时,才会返回 true。 
in的话,是分不清在属性存在于原型还是实例中的。因此只要 in 操作符返回 true 而 hasOwnProperty() 返回 false,就可以确定属性是原型中的属性,下面封装一个方法:

1 function hasPrototypeProperty(object, name){
2     //属性是原型中的属性
3     return !object.hasOwnProperty(name) && (name in object);
4 }

 

用字面量写法,让原型模式更简洁

 1 function Person(){
 2 }
 3 Person.prototype = {
 4     name : "Nicholas",
 5     age : 29,
 6     job: "Software Engineer",
 7     sayName : function () {
 8         alert(this.name);
 9     }
10 };

 

这样写后,constructor就不会再指向Person,因为重写了Person.prototype。需要重新指定constructor的指向。

 1 function Person(){
 2 }
 3 Person.prototype = {
 4     constructor : Person,
 5     name : "Nicholas",
 6     age : 29,
 7     job: "Software Engineer",
 8     sayName : function () {
 9         alert(this.name);
10     }
11 };

 

原型动态性,实例与原型之间的链接是一个指针,而非一个副本。所以,原型上的任何修改都能立即在实例上表现出来,即使是实例创建在先。

1 var friend = new Person();
2 Person.prototype.sayHi = function(){
3     alert("hi");
4 };
5 friend.sayHi(); //"hi" (没有问题!)

 

但是如果是重写整个原型对象(字面量形式),那就不一样了(先实例后原型)

 1 function Person(){
 2 }
 3 var friend = new Person();
 4 Person.prototype = {
 5     constructor: Person,
 6     name : "Nicholas",
 7     age : 29,
 8     job : "Software Engineer",
 9     sayName : function () {
10         alert(this.name);
11     }
12 };
13 friend.sayName(); //error

 

此处输入图片的描述 
原型模式的缺点,对于包含引用类型值的属性来说,某个实例的属性赋值,会影响到所有实例。

 
 1 function Person(){
 2 }
 3 Person.prototype = {
 4     constructor: Person,
 5     name : "Nicholas",
 6     age : 29,
 7     job : "Software Engineer",
 8     friends : ["Shelby", "Court"],
 9     sayName : function () {
10         alert(this.name);
11     }
12 };
13 var person1 = new Person();
14 var person2 = new Person();
15 //person1.friends = [];//如果先创建的话,那么这个friends就是person1的,但是这样就没法保留原型中的值。
16 person1.friends.push("Van");//这个friends是原型的。
17 alert(person1.friends); //"Shelby,Court,Van"
18 alert(person2.friends); //"Shelby,Court,Van"
19 alert(person1.friends === person2.friends); //true

 

所以开始引入构造函数+原型模式 :构造函数模式用于指定实例属性,原型模式用于定义方法和共享的属性。

 1 function Person(name, age, job){
 2     this.name = name;
 3     this.age = age;
 4     this.job = job;
 5     this.friends = ["Shelby", "Court"];
 6 }
 7 Person.prototype = {
 8     constructor : Person,
 9     sayName : function(){
10         alert(this.name);
11     }
12 }
13 var person1 = new Person("Nicholas", 29, "Software Engineer");
14 var person2 = new Person("Greg", 27, "Doctor");
15 person1.friends.push("Van");
16 alert(person1.friends); //"Shelby,Count,Van"
17 alert(person2.friends); //"Shelby,Count"
18 alert(person1.friends === person2.friends); //false
19 alert(person1.sayName === person2.sayName); //true

 

最完美的模式来了,动态原型模式。不能使用对象字面量重写原型。和构造函数+原型的区别是,new的时候才会给原型添加属性。

 1 function Person(name, age, job){
 2     //属性
 3     this.name = name;
 4     this.age = age;
 5     this.job = job;
 6     //方法
 7     if (typeof this.sayName != "function"){
 8         Person.prototype.sayName = function(){
 9             alert(this.name);
10         };
11     }
12 }
13 var friend = new Person("Nicholas", 29, "Software Engineer");
14 friend.sayName();

四、继承

 最完美的继承:寄生组合式继承

 1  function object(o){
 2    function F(){}
 3    F.prototype = o;
 4    return new F();
 5   }
 6   function inheritPrototype(subType, superType){
 7    var prototype = object(superType.prototype); //创建对象
 8    prototype.constructor = subType; //增强对象
 9    subType.prototype = prototype; //指定对象
10   }
11   function SuperType(){
12     this.property = true;
13     this.arr = [1,2,3];
14   }
15   SuperType.prototype.getSuperValue=function(){
16     return this.property;
17   }
18   function SubType(){
19     SuperType.call(this);
20     this.subproperty = false;
21   }
22   inheritPrototype(SubType,SuperType);
23 
24   SubType.prototype.getSubValue=function(){
25     return this.subproperty;
26   }
27   var o = new SubType();
28   console.log(o);

免责声明:文章转载自《Javascript高级程序设计3笔记》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇30 个超棒的杂志用的 WordPress 主题安装ucenter 步骤详解及supesite 安装详解下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

小程序02 wxml和wxss

微信小程序的排版就跟wxml和wxss有关,它们两者相当于HTML和CSS,其中wxml指定了界面的框架结构,而wxss指定了界面的框架及元素的显示样式。 一、wxml 界面结构wxmL比较容易理解,主要是由八大类基础组件构成:   一、视图容器(View Container): 二、基础内容(Basic Content) 组件名 说...

pymysql完成数据的查询操作

import pymysql # 创建连接对象 conn = pymysql.connect(host='localhost', port=3306, user='root', password='mysql',database='python', charset='utf8') # 获取游标对象 cursor = conn.cursor() # 查...

JavaEE 对象的串行化(Serialization)

什么情况下需要序列化 a)当你想把的内存中的对象写入到硬盘的时候;b)当你想用套接字在网络上传送对象的时候;c)当你想通过RMI传输对象的时候;再稍微解释一下:a)比如说你的内存不够用了,那计算机就要将内存里面的一部分对象暂时的保存到硬盘中,等到要用的时候再读入到内存中,硬盘的那部分存储空间就是所谓的虚拟内存。在比如过你要将某个特定的对象保存到文件中,我隔...

Android学习笔记12:图像渲染(Shader)

在Android中,提供了Shader类专门用来渲染图像以及一些几何图形。   Shader类包括了5个直接子类,分别为:BitmapShader、ComposeShader、LinearGradient、RadialGradient以及SweepGradient。其中,BitmapShader用于图像渲染;ComposeShader用于混合渲染;Line...

Web前端开发最佳实践(9):CSS代码太太乱,重复代码太多?你需要精简CSS代码

前言 提高网站整体加载速度的一个重要手段就是提高代码文件的网络传输速度。之前提到过,所有的代码文件都应该是经过压缩了的,这可提高网络传输速度,提高性能。除了压缩代码之外,精简代码也是一种减小代码文件大小的手段。以下将讨论CSS代码相关的代码精简方案。 定义简洁的CSS规则 CSS的每条规则中都包含了规则的属性及属性值。定义简洁的CSS规则主要是指合并相关规...

Python学习之JSON格式的序列化和反序列化

查看json库的方法 import json print("JSON库的主要方法:",json.__all__) ###JSON库的主要方法: ['dump', 'dumps', 'load', 'loads', 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder']dump和dumps的区别 dump是将对象...