《JavaScript高级程序设计》是一本好书,下面总结一下书中关于原型链的讲解。
本文从对象的创建开始,逐渐引出原型链的背景、作用以及ECMA对原型链的定义
1、理解对象
两种常用的创建对象的方法之一是new一个Object对象,并为它添加属性和事件
var person = new Object();
person.name = "wzk";
person.age = 24;
person.sayName = function(){
alert(this.name);
};
另一种是使用对象字面量创建对象
var person = {
name : "wzk",
age : 24;
sayName : function(){
alert(this.name);
}
}
以类似键值对的形式给出每个变量或者函数的定义,注意以逗号分隔,最后一个属性不需要加逗号
两种方法纯粹是写法不同,首推后者。
以上两种方法适合创建单个对象,创建多个对象将造成代码重复。
2、用接口创建对象
2.1、工厂模式
function createPerson(name ,age){
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function(){
alert(this.name);
}
return 0;
}
var person1("wzk",24);
var person2("cxl","18");
实际上就是上述第一种方法套在函数中的写法
缺点是无法利用instanceof函数识别创建出来的对象
2.2、构造函数模式(惯例首字母大写,与普通函数区别开)
function Person(name,age){
this.name = name;
this.age = age;
this.sayName = function(){
alert(this.name);
}
}
var person1 = new Person("wzk",24);
var person2 = new Person("cxl",18);
与工厂模式的区别:
1、没有创建Object对象
2、属性方法直接赋给了this对象
3、没有return
实际上,上述函数看起来就像一个普通函数,this在浏览器中就是指window对象
但是使用new创建,就区别于普通函数,成为构造函数
所以,所有构建对象的动作都是由new做的,动作如下:
1、创建一个新对象
2、将构造函数的作用域赋给创建的新对象,即this指向该新对象
3、为新对象添加属性、方法
4、返回这个新对象
可以使用instanceof判断对象类型
alert(person1 instanceof Person); //true
alert(person2 instanceof Person); //true
构造函数的缺点:
由于ECMAScript中,函数是对象
所以实例person1与person2中的sayName()方法是两个
不同的对象,他们被重复创建,而功能却是一样的。
解决办法:
将sayName()函数移到构造函数外,使构造函数内的sayName函数
指向构造函数外的函数,但带来的新问题:
1、只能被特定对象调用
2、封装性被破坏
下面,终于引出了原型模式解决该问题
原型模式:
函数即对象,在我们创建每一个函数时,每个函数都会自动生成
一个prototype(原型)属性。prototype属性指向一个对象,
该函数的所有实例可以共享该对象的属性和方法。
构造函数也是函数,所以由构造函数生成的每一个对象实例都可以通过
prototype访问这个对象的属性和方法。
prototype指向的这个对象即为该函数的原型对象。
function Person(){
}
Person.prototype.name = "wzk";
Person.prototype.age = 24;
Person.prototype.sayName = function(){
alert(this.name);
}
var person1 = new Person();
var person2 = new Person();
person1.sayName(); //wzk
person2.sayName(); //wzk
alert(person1.sayName == person2.sayName); //true
原型对象:
当创建函数的时候,就会为该函数创建一个prototype属性
,该属性指向函数的原型对象。同时圆形对象会获得一个
constructor(构造函数)属性,指回函数。
即Person.prototype = 原型对象
Person.prototype.constructor = Person