原型(公用属性)
在 javascript 中,函数都是对象,可以有属性。 每个函数都有一个特殊的属性叫作原型(prototype),这个属性会指向函数的原型对象。JavaScript 的原型对象中,还包含了一个 constructor
属性,这个属性对应创建所有指向改原型的实例的构造函数。
每个对象都有
__proto__
属性,但只有函数对象才有prototype
属性。
在使用构造函数生成实例的时候,prototype 属性会成为该对象实例的原型。constructor 指向该实例的构造函数(prototype 属性所在的函数)。
上述代码中,Foo
为构造函数,p1
与 p2
是该构造函数的实例对象,Foo
的 prototype
属性就是这两个实例的原型对象,所以它们都可以使用.age
方法,这个方法在两个实例的__proto__
属性中。constructor
属性指向含有该原型的构造函数 Foo
。
实例对象.__proto__ === 函数.prototype
原型对象的属性不是实例对象自身的属性。只要修改原型对象,变动就立刻会体现在所有实例对象上。这是因为实例对象其实没有age
属性,都是读取原型对象的age
属性。当实例对象本身没有某个属性或方法的时候,它会到原型对象去寻找该属性或方法。
如果某个实例对象自身就有某个属性或方法,它就不会再去原型对象寻找这个属性或方法,所以改变原型对象上的值也不会影响该实例。
构造函数生成的实例只有__proto__
属性,没有prototype
属性。
原型链
当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用。如果没有则去原型的原型中寻找,直到找到Object对象的原型,Object对象的原型没有原型,如果在
Object. prototype
中依然没有找到,则返回undefined
。
Object是JS中所有对象数据类型的根基,在Object.prototype
上的__proto__
属性指向null
。重要公式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15var 对象 = new 函数()
对象.__proto__ === 对象的构造函数.prototype
// 推论
var number = new Number()
number.__proto__ = Number.prototype
Number.__proto__ = Function.prototype // 因为 Number 是 Function 的实例
var object = new Object()
object.__proto__ = Object.prototype
Object.__proto__ = Function.prototype // 因为 Object 是 Function 的实例
var function = new Function()
function.__proto__ = Function.prototype
Function.__proto__ == Function.prototye // 因为 Function 是 Function 的实例!__proto__
和prototype
的区别是什么?- 不能断章取义,
__proto__
和prototype
只是两个 key 而已。 - 我们一般研究对象的
__proto__
和函数的prototype
。 对象.__proto__ === 某函数.prototype
。- 如果把函数看成对象,那么
函数.__proto__ === Function.prototype
。 - 如果把 Function 看成对象,那么
Function.__proto__ === Function.prototype
。
- 不能断章取义,