最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 这一次彻底理清JavaScript的原型链

    正文概述 掘金(酔墨)   2021-01-09   374

    1. JavaScript原型

    1. Object

    在谈论JS中的原型之前,有必要先来了解一下JS中的 Object。 Object作为JS的原始类型之一,它是由键值对的形式构成,键名可以为String或Symbol,键值可以为JS中的任意类型。通常创建Object的方式有三种

    
    let obj1 = {}; // 字面量方式创建 Object
    let obj2 = Object.create(); // ES5中新增的Object.create()
    let obj3 = new Constructor() // 通过new 关键字来创建构造函数的实例,实例就是一个Object
    

    而今天要说的就是通过 new Constructor() 生成Object的方式来理解原型以及原型链

    2. 原型

    JS中当调用 new Constructor() 之后,会生成一个 Object 。 这个Object 自动拥有 Constructor 内部的属性。

    function Person(name, age) {
    this.name = name;
    this.age = age;
    this.say = function () {
    console.log(`my name is ${this.name} and I am ${this.age} years old`);
    }
    }
    // 实例会继承构造函数的全部属性 对象的方法其实也是它的一种属性
    const mike = new Person('mike', 11)
    const jack = new Person('jack', 12)
    console.log(mike); // Person {name: "mike", age: 11, say: ƒ}
    console.log(jack); // Person {name: "jack", age: 12, say: ƒ}
    mike.say() // my name is mike and I am 11 years old
    jack.say() // prototype.js:12 my name is jack and I am 12 years old
    

    而在创建Object的过程中,JS会自动的创建一个Object,且称他为prototypeObject ,并将 Constructor的prototype属性指向prototypeObject,于此同时,prototypeObject内部有一个constructor 属性指向Constructor ,所以会有

    console.log(Person.prototype.constructor === Person); // true
    

    prototypeObject便叫做Constructor的原型 ,Constructot叫做构造函数,而Object叫做实例(Instance)。对于一个构造函数函数来说可以拥有无数个实例,而每个实例仅仅只存在一个构造函数。对于实例与原型的关系来说,根据ECMAScript 标准规定:

    实例内部存在一个 [[prototype]] 的属性链接到原型上,通过这个属性可以在实例中访问到原型上的属性与方法。

    不过现在的主流浏览器都实现了__proto__的属性,通过访问实例的__proto__属性,可以找到原型对象:

    // 在 chrome浏览器中
    console.log(mike.__proto__ === Person.prototype); // true
    
    Person.prototype.eat = function() {
    console.log(`${this.name} is eating!`);
    }
    mike.eat() // mike is eating!
    jack.eat() // jack is eating!
    
    

    那么现在应该很清楚构造函数、原型以及实例之间的关系了吧,让我们用图形来总结一下:
    这一次彻底理清JavaScript的原型链

    1. 通过构造函数可以创建无数个实例,一个构造函数对应众多实例,
    2. 一个构造函数对应一个原型,即原型与构造函数是一对一的,
    3. 原型与实例也是一对多的关系,众多的实例会共享原型的属性,

    所以在当调用实例的某个属性时,如果实例中不存在,那么JS就会自动去实例的原型里面查找这个属性。倘若原型里面也没有找到的话,又将会发生什么样好玩的事呢?

    2. 原型链

    理解了第一点的原型结构,那么再来理解原型链就变得很容易了。从第一点我们可以知道当访问实例的属性时,若该属性不存在实例中,那么JS会自动的去实例原型中去查找,而我们知道,实例原型同样也是一个Object,所以按照Object的规则,它肯定也会拥有构造函数以及原型(原型的原型,听起来比较绕...),所以在实例与原型之间就形成了一条如下的链式结构
    这一次彻底理清JavaScript的原型链
    即 instance -> prototype -> prototype1 形成一条链式结构,当我们执行instance.data 时,JS引擎会

    1. 在 instance中查找data属性,如果instance内存在data属性,那么会返回 instance内部的data属性
    2. 如果在 instance中没有查找到data属性,那么会去prototype 内部查找,如果找到,那么会返回 prototype内部的data属性
    3. 如果在 prototype中没有查找到data属性,那么会去prototype1 内部查找,如果找到,那么会返回 prototype1内部的data属性
    4. 如果一直查到最顶层的原型中都没找到的话,那么会返回 underfine

    以上就是 JS引擎基于原型链查找属性的行为,那么现在还有一个问题,最顶层的原型是谁

    3. 原型链的另一端

    我们可以通过一个实例来一直向上查找,来看看原型链最顶层的元素,以上面的实例mike为例:

    console.log(mike.__proto__) // {eat: ƒ, constructor: ƒ}
    console.log(mike.__proto__.__proto__) // { constructor: ƒ Object() ... }
    console.log(mike.__proto__.__proto__.__proto__) // null
    

    上面我们可以看到在原型链最顶端的竟然是 null ,而原型为null 的实例的constructor 是JS内置的Object,那么这个以null 为原型的实例可以表示为Object.prototype 。由此可以写出一条完整的链式结构图:
    这一次彻底理清JavaScript的原型链

    所以一条JS完整的原型链就表示出来了,在访问实例属性的时候会沿着上图的顺序,从上往下依次查找直到查找到null。

    总结

    在JS中,原型链是比较基础的知识,同时也是比较重要的知识,js 引擎在访问对象中的属性时会沿着原型链一次一次向上查找,所以可以通过这个特性,可以使得前端很灵活的使用 JS 的继承特性来方便的实现想要的效果。


    起源地下载网 » 这一次彻底理清JavaScript的原型链

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元