js中原型链理解

本文固定连接:https://blog.****.net/u011135729/article/details/79813174

假设有这么一段代码:

    function fn(){
this.prop = {};
}
var o = new fn();
console.log(o.__proto__ === fn.prototype); //true
console.log(fn.prototype.__proto__ === Object.prototype); //true
console.log(Object.prototype.__proto__); //null
从输出的结果可以看出来,整条原型链为:
    1、o.__proto__ ---> fn.prototype, 
    2、fn.prototype.__proto__ ---> Object.prototype 
    3、Object.prototype.__proto__ ---null 原型链结束

js中原型链理解

如果存在继承关系,则子类的原型对象的__proto__属性(son.prototype.__proto__)会指向父类的原型对象(father.prototype),father.prototype.__proto__ 再继续指向父类的父类的原型对象,以此类推,最后指向Object.prototype

例如:

    //es5中才有的Object.create,这里先这样兼容一下吧(可以参考最下方的参考链接查看兼容的浏览器)
if (typeof Object.create !== "function") {
Object.create = function (proto, propertiesObject) {
if (typeof proto !== 'object' && typeof proto !== 'function') {
throw new TypeError('Object prototype may only be an Object: ' + proto);
} else if (proto === null) {
throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.");
}
if (typeof propertiesObject != 'undefined') throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument.");
function F() {}
F.prototype = proto;
return new F();
};
}

function grandpa(name){
this.name = name;
}
grandpa.prototype = {
getName : function(){
console.log('my name is '+this.name);
}
}
function father(name){
grandpa.call(this,name);
}
father.prototype = Object.create(grandpa.prototype);
father.prototype.constructor = father;
function son(name){
father.call(this,name);//这样写目的是让son的实例也拥有父类函数内部的属性与方法(非prototype);
};
son.prototype = Object.create(father.prototype);
son.prototype.constructor = son;//这样的是将实例的construction指向son 即 实例.constructor 的值为 ‘function son(name){father.call(this,name);}’
var sonModel = new son('son');
console.log(sonModel.name);//son
sonModel.getName();//my name is son
这段代码的意思是:son继承自father,father继承自grandpa(当然js可以实现多继承,但是针对多继承的情况,原型链在我认为来说是错误的,因为他只链了第一个继承的原型对象(用jquery的写法的话,也有可能连到其他父对象,但是只能链一个))

js中原型链理解

原型链在属性搜索中的作用:

    寻找一个属性会遍历整条原型链

    Object.prototype.d = 4;
function fn(){
this.a = 1;
}
fn.prototype.b = 2;
fn.prototype.c = 3;
function fn2(){
fn.call(this);
this.c = 'fn2中的c';
}
fn2.prototype = Object.create(fn.prototype);
var fn2Model = new fn2();
console.log(fn2Model.c); //fn2中的c
console.log(fn2Model.d); //4

    上面这段代码,fn2Model对象本身只有a c两个属性(直接被注册到this上了),同时,在fn.prototype中b c两个属性被继承,但最后fn2Model.c的值为‘fn2中的c’,fn2Model.d的值为4,可以得出结论

    属性的搜索机制:先搜索实例对象本身具有的属性(如果写法中在子类内部不写 父类.call(this) ,那么可以理解为是方法内部的属性),找到则返回,找不到则会找原型,一次顺着原型链依次向上查找,直到原型链结束。

    包括枚举一个实例对象时候,也会通过原型链查找到原型链结束 即Object.prototype.__proto__

    Object.prototype.d = 4;
function fn(){
this.a = 1;
this.b = 2;
}
fn.prototype.c = 3;
fn.prototype.getName = function(){
console.log(this.a+this.b+this.c+this.d);
};
var o = new fn();
for(var item in o){
console.log(item);//打印结果 a b c getName d
}
o.getName();//10
从输出的结果来看,枚举的属性还包括了d,而fn函数本身是没有这个属性的,且fn.prototype.__proto__最终是指向Object.prototype,所以最终枚举的属性包含了d。
本文固定连接:https://blog.****.net/u011135729/article/details/79813174
参考链接:
    https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
    https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create