当前位置: 首页 > Web前端 > JavaScript

js继承与原型链看这篇文章就够了

时间:2023-03-27 14:12:18 JavaScript

继承与原型链谈到继承,JavaScript只有一种结构:对象。每个实例对象(object)都有一个私有属性(称为proto)指向其构造函数(prototype)的原型对象。原型对象也有自己的原型对象(proto),一层一层直到某个对象的原型对象为null。根据定义,null没有原型,充当此原型链中的最后一环。JavaScript中几乎所有的对象都是原型链顶端的Object的实例。继承属性JavaScript对象是属性的动态“包”(指它自己的属性)。JavaScript对象有一个指向原型对象的链。当尝试访问对象的属性时,它不仅会在对象上搜索,还会在对象的原型上搜索,然后在对象原型的原型上搜索,依此类推,直到找到具有匹配名称的属性或到达原型链的末端。代码示例functionfn(){this.a=1;这个.b=2;}consto=newfn();fn.prototype.b=3;fn.prototype.c=4;console.log(o.a);console.log(o.b);console.log(o.c);console.log(o.d);//1//2//4//undefinedcopycodea和b是o自己的属性和可以直接返回值我们设置fn.prototype.b=3,还是2吗?,因为我们搜索这个属性的时候,直接返回,不会去搜索。c不是o的自有属性,所以会去o.prototype中搜索找到c,直接返回值d。搜索,找到null,停止搜索,返回undefined看oconstructor{a:1b:2__proto__:b:3c:4constructor:?fn()__proto__:constructor:?Object()hasOwnProperty:?hasOwnProperty()isPrototypeOf:?isPrototypeOf()propertyIsEnumerable:?propertyIsEnumerable()toLocaleString:?toLocaleString()toString:?toString()valueOf:?valueOf()__defineGetter__:?__defineGetter__()__defineSetter__:?__defineSetter__()__lookupGetter__lookter__:?__lookupSetter__()get__proto__:?__proto__()set__proto__:?__proto__()}复制代码继承方法JavaScript没有其他基于类的语言定义的“方法”。在JavaScript中,任何函数都可以作为对象的属性添加到对象中。函数继承与其他属性继承没有区别,包括上面的“属性阴影”(这种情况相当于其他语言的方法重写)。调用继承函数时,this指向当前继承对象,而不是继承函数所在的原型对象。varo={a:2,m:function(){returnthis.a+1;},};console.log(o.m());//3//调用o.m时,'this'指向o.varp=Object.create(o);//p是继承自o的对象p.a=4;//创建p自己的属性'a'console.log(p.m());//5//调用p.m的时候,'this'指向p//因为p继承了o的m函数//所以,此时的'this.a'就是p.a,也就是p自己的属性'a'复制代码并在JavaScript中使用原型在JavaScript中,函数是允许有属性的。所有的函数都会有一个特殊的属性——原型。默认是Object的原型对象functiondoSomething(){}console.log(doSomething.prototype);//与声明函数的方式无关,//JavaScript中的函数总是有一个默认的原型属性。vardoSomething=function(){};控制台日志(doSomething.prototype);复制代码在控制台显示的JavaScript代码块中,我们可以看到doSomething函数的默认属性原型。运行此代码后,控制台应显示类似于以下内容的内容:propertyIsEnumerable(),toLocaleString:?toLocaleString(),toString:?toString(),valueOf:?valueOf()}}我们可以向doSomething函数的原型对象添加新属性,如下所示:functiondoSomething(){}doSomething。prototype.foo="bar";console.log(doSomething.prototype);复制代码运行后看结果:?propertyIsEnumerable(),toLocaleString:?toLocaleString(),toString:?toString(),valueOf:?valueOf()}}现在我们可以通过new操作符创建一个基于这个原型对象的doSomething实例。代码:函数doSomething(){}doSomething.prototype.foo="bar";//在原型上添加一个属性vardoSomeInstancing=newdoSomething();doSomeInstancing.prop="一些值";//在对象控制台上添加一个属性.log(doSomeInstancing);复制代码运行的结果类似于下面的语句。{prop:"somevalue",__proto__:{foo:"bar",constructor:?doSomething(),__proto__:{构造函数:?Object(),hasOwnProperty:?hasOwnProperty(),isPrototypeOf:?isPrototypeOf(),propertyIsEnumerable:?propertyIsEnumerable(),toLocaleString:?toLocaleString(),toString:?toString(),valueOf:?valueOf()}}}复制代码可以看到prop是doSomeInstancing的属性,doSomeInstancing中的proto是doSomething。原型。打印console.log("doSomeInstancing.prop:"+doSomeInstancing.prop)中的属性;console.log("doSomeInstancing.foo:"+doSomeInstancing.foo);console.log("doSomething.prop:"+doSomething.prop);console.log("doSomething.foo:"+doSomething.foo);console.log("doSomething.prototype.prop:"+doSomething.prototype.prop);console.log("doSomething.prototype.foo:"+doSomething.prototype.foo);复制代码的结果如下://doSomeInstancing自身的属性,直接返回值doSomeInstancing.prop:somevalue//它不是doSomeInstancing的属性。查看原型对象,发现这个属性直接返回值doSomeInstancing.foo:bar//不是函数本身的属性,也不是原型对象的属性。一层层查找,最后发现原型为null时,说明没有这个属性,所以返回undefineddoSomething.prop:undefineddoSomething.foo:undefineddoSomething.prototype.prop:undefined//找到doSomething原型对象有foo属性,所以直接返回值doSomething.prototype.foo:barCopycodeperformanceinLookinguppropertiesontheprototypechain很耗时并且对性能有副作用,这在性能关键的情况下很重要。另外,当试图访问一个不存在的属性时,会遍历整个原型链。在遍历对象的属性时,会枚举原型链上的每个可枚举属性。要检查对象是否具有自己定义的属性,而不是其原型链上的属性,必须使用所有对象都继承自Object.prototype的hasOwnProperty方法。下面给出一个具体的例子来说明:"foo"));//falseconsole.log(doSomeInstancing.__proto__.hasOwnProperty("foo"));//true复制代码hasOwnProperty是JavaScript中唯一处理属性且不遍历原型链的方法。另一个这样的方法:Object.keys()注意:检查属性是否未定义并不会检查它是否存在。该属性可能已经存在,但它的值恰好被设置为未定义。https://zhuanlan.zhihu.com/p/...https://zhuanlan.zhihu.com/p/...https://zhuanlan.zhihu.com/p/...https://zhuanlan.zhihu.com/p/...https://zhuanlan.zhihu.com/p/...https://zhuanlan.zhihu.com/p/...https://zhuanlan.zhihu.com/p/...https://zhuanlan.zhihu.com/p/...https://zhuanlan.zhihu.com/p/...