面向对象编程很重要的一个方面,就是对象的继承。A对象通过继承B对象,就能直接拥有B对象的所有属性和方法。这对于代码的复用是非常有用的。
大部分面向对象的编程语言,都是通过“类”来实现对象的继承,JavaScript语言的继承则是通过“原型对象”(prototype)。
prototype
与 __proto__
prototype
原型对象的作用
看一段代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//构造函数
function person(name){
this.name = name;
}
//生成对象
var jack = new person('jack');
console.log(jack); //打印结果为 person{name: 'jack'}
consoloe.log(jack.name); //打印结果为jack
console.log(jack.gender); //打印结果为 undefined
//为构造函数的原型对象添加属性
person.prototype.gender = 'male';
console.log(jack.gender); //打印结果为 male
- 以上代码构造了一个函数person
- 生成对象jack,对象jack的gender打印结果是undefined
- 将函数person的
prototype
原型对象的属性gender设为 ‘male’ - 此时原本对象jack中没有的属性gender,打印出的值为 ‘male’
- 由于设置
prototype
的gender属性这个动作,实现了属性的共享 - 因此每个构造函数都有一个prototype原型对象
JavaScript继承机制的设计思想就是,
prototype
原型对象的所有属性和方法,都能被实例对象共享.也就是说,如果属性和方法定义在原型上,那么实例对象就能共享,不仅节省了内存,还体现了实例对象之间的联系.
__proto__
属性
看一段代码1
2
3
4
5
6var n1 = 1;
var n2 = new Number(1);
console.log(n1); //打印结果为 1
console.log(n2); //打印结果为 Number {1}
console.log(n1.toString()); //打印结果为 '1'
- 声明n1为普通类型数字1,声明n2为数字函数构造1
- 仅从打印结果来看,n1是普通类型没有属性,只有对象有属性,但是在toString的过程中,JavaScript会将数字(简单类型)转化为对象(复杂类型),并从复杂类型中寻找toString()对应的值
- 不必要给每个对象一个toString和valueOf,JavaScript的做法是把toString和valueOf放在一个公用属性对象里,然后让每个对象的
__proto__
存储这个公用属性对象 - 每个对象都有一个
__proto__
属性,并且指向它的prototype
原型对象
重要公式
var 对象 = new 函数();
对象.__proto__ === 函数.prototype;1
2
3
4
5//由公式可知
Object.__proto__ === Function.prototype
Function.__proto__ === Function.prototype
Function.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ === null总结
- 当new一个构造函数时,则创建了一个函数实例,那么 函数实例.__proto__ === 该构造函数.prototype
- 所有函数都是有
Function
,那么 被构造出来的函数.__proto__ === Function.prototype - 所有构造函数的原型对象都是由Object构造出来的,那么 所有构造函数.prototype.__proto__ === Object.prototype
原型链
JavaScript规定,素有对象都有自己的原型对象(
prototype
)一方面任何一个对象,都可以充当其他对象的原型,另一方面原型对象也是对象,所以它有自己的原型,因此就会形成一个原型链:对象到原型,再到原型的原型
如果一层层地上溯,所有对象的原型最终都可以上溯到
Object.prototype
,即Object构造函数的prototype
属性.也就是说,所有对象都继承了Object.prototype
的属性Object.prototype
的原型是null,由于null没有任何属性,原型链便到此为止
number ---> Number.prototype ---> Object.prototype ---> null
