阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      JavaScript 的原型,原型链都有什么特点?

      问题

      JavaScript的原型,原型链都有什么特点?

      参考答案

      • 原型对象也是普通的对象,是对象一个自带隐式的 __proto__ 属性,原型也有可能有自己的原型,如果一个原型对象的原型不为null的话,我们就称之为原型链
      • 原型链是由一些用来继承和共享属性的对象组成的(有限的)对象链

      详细的总结

      原型链一直是个很抽象的概念,看不到,摸不着.随着最近对JavaScript进一步的学习,我对原型链有了一点理解,下面讲出来.

      基础知识

      在JavaScript中,一共有两种类型的值,原始值和对象值.每个对象都有一个内部属性prototype,我们通常称之为原型.

      原型的值可以是一个对象,也可以是null.如果它的值是一个对象,则这个对象也一定有自己的原型.这样就形成了一条线性的链,我们称之为原型链.

      访问一个对象的原型可以使用Object.getPrototypeOf方法,或者__proto__属性.

      原型链的作用是用来实现继承,比如我们新建一个数组,数组的方法就是从数组的原型上继承而来的.

      var arr = [];
      arr.map === Array.prototype.map //arr.map是从arr.__proto__上继承下来的,arr.__proto__也就
      

      Array.prototype

      图形化原型链

      虽然我们都说原型链,但实际上,在不考虑网页中frame的情况,js引擎在执行期间的某一时刻,所有存在的对象组成的是一棵原型树.

      默认情况下,只有一棵树.根节点可以说是Object.prototype,也可以说是null.

      但我们可以再建立一棵原型树,通过使用Object.create方法

      var foo = Object.create(null); //foo是一个对象,但它是游离的,不属于已有的那棵原型树
      var bar = Object.create(foo); //bar的原型是foo
      var baz = Object.create(foo); //baz的原型是foo 
      

      这样我们有了第二棵原型树

      遍历原型链

      我们没有办法遍历到所有以某个对象为原型的对象,但我们可以向上遍历,获取到一个对象所有的上层原型,这个原型链必定是线性的,尽头是null.

      function getPrototypeChain(object) {
        var protoChain = [];
        while (object = object.__proto__) {
          protoChain.push(object);
        }
        protoChain.push(null);
        return protoChain;
      }
      

      试验一下,不同的环境实现不同,显示形式也不同.下面是在chrome控制台中的显示.

      >getPrototypeChain(new String(""))
      [String, Object, null] //依次是String.prototype,Object.prototype,null
      
      >getPrototypeChain(function(){})
      [function Empty() {}, Object, null] //依次是Function.prototype,Object.prototype,null
      

      内置类型的对象的原型链并不长,下面试试宿主对象.

      >getPrototypeChain(document.createElement("div"))
      [HTMLDivElement, HTMLElement, Element, Node, Object, null]
      

      这个就长多了.

      超长原型链

      可以看出来,我们平时使用的对象并没有很长的原型链.但可以自己构造一个.

      function Foo() {}
      
      for (var i = 0; i < 100; i++) {
      Foo.prototype["foo" + i] = i;
      Foo.prototype = new Foo;
      }
      console.dir(getPrototypeChain(new Foo));
      

      最后的这个new Foo有多少个上层原型呢?

      经典的总结

      每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,

      如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype

      于是就这样一直找下去,也就是我们平时所说的原型链的概念。

      关系

      instance.constructor.prototype = instance.__proto__
      

      特点

      JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。

      当我们修改原型时,与之相关的对象也会继承这一改变。

      当我们需要一个属性的时,Javascript引擎会先看当前对象中是否有这个属性, 如果没有的话,

      就会查找他的prototype对象是否有这个属性,如此递推下去,一直检索到 Object 内建对象。

      function Func () { }
      Func.prototype.name = "Sean";
      Func.prototype.getInfo = function () {
        return this.name;
      }
      var person = new Func();//现在可以参考var person = Object.create(oldObject);
      console.log(person.getInfo());//它拥有了Func的属性和方法
      //"Sean"
      console.log(Func.prototype);
      // Func { name="Sean", getInfo=function()}
      

      更多面试题

      如果你想了解更多的前端面试题,可以查看本站的WEB前端面试题 ,这里基本包涵了市场上的所有前端方面的面试题,也有一些大公司的面试图,可以让你面试更加顺利。

      面试题
      HTMLCSSJavaScript
      jQueryVue.jsReact
      算法HTTPBabel
      BootStrapElectronGulp
      Node.js前端经验相关前端综合
      Webpack微信小程序-

      这些题库还在更新中,如果你有不错的面试题库欢迎分享给我,我整理后放上来;人人为我,我为人人,互帮互助,共同提高,祝大家都拿到心仪的Offer!

      目录
      目录