var Person = function (name) { this.name = name; } Person.prototype.say = function () { console.log(this.name); } var p = new Person('hello'); p.say(); // 'hello'
这是一个最简单的面向对象的写法,那为什么通过 new 方法后赋值给 p 后 ,p可以调用say()方法!
我们来看看 new 为我们做了些什么
1.var p = {}; 2.p.__proto__ = Person.prototype; 3.Person.call(p); 步骤1:初始化一个空对象 步骤2:将这个对象的 __proto__ 指向 Person.prototype 步骤3:初始化p
__proto__是什么鬼?
每一个对象的内部都会有一个__proto__属性,当我们想要查找某个对象的某个属性时,如果没有,他就会去__proto__属性里面去找,如果还是没找到,而__proto__属性里面又包含一个__proto__,就又去__proto__的__proto__里面去找.........,一直找到Object里面,如果还没有,就真的没有了!!
你可能有点晕,但是这就是js中的原型链机制,而这个__proto__就是这个链子。
这是 console.log(p) 产生的结果!
位置1: p.__proto__ 指向了一个对象,而这个对象就是 Person.prototype
位置2:这个__proto__是属于Person.prototype的,他指向Object.prototype
console.log(p.__proto__ == Person.prototype); // true console.log(Person.prototype.__proto__ == Object.prototype); //true
现在我们可以解释为啥p可以调用say()方法,p自己没有say()方法,但是因为它的__proto__属性指向了Person.prototype
恰巧 Person.prototype有say()方法,那要是Person.prototype里面还是没有呢?,那就去Person.prototype.__proto__
指向的Object.prototype里面去找,要是还是没有,那就真的没有了
这是一张脑图!非常形象的描述了js原型继承的机制
我们可以把上面的Cat mycat 换成我们的 Person p
console.log(p.__proto__ == Person.prototype);//true console.log(Person.prototype.__proto__ == Object.prototype); //true console.log(Person.__proto__ == Function.prototype); //true console.log(Function.prototype.__proto__ == Object.prototype); //true console.log({}.__proto__ == Object.prototype); //true
__proto__ __proto__ __proto__
A——————————》B——————————》C——————————》Object.prototype
所有对象最终都指向Object.prototype
A里面有就用A里面的,不会再去找了,如果没有就通过原型链去连接的B里面找,如果有就用B里面的,如果没有就去B连接的C里面去找,
如果C有,就用C的,如果没有就去Object.prototype找,如果还是没有,就真的没有了!!!