原型&&原型链

141 阅读1分钟

扩展:

当 new Foo(), 发生了什么?

  • 创建了一个新空对象;
  • 将 this 指向了这个新空对象;
  • 执行构造函数里面的代码;
  • 返回这个新对象;

原型&&原型链

  • js 中每个实例对象都有一个 __proto__ 属性,该属性指向它的原型对象,这个实例对象的构造函数有一个原型属性 prototype 属性,与实例的 __proto__ 属性指向同一个对象;

    let arr = []
    console.log(Array.prototype === arr.__proto__);  // true
    
    function Person(name) {
      this.name = name
    }
    let p1 = new Person()
    
    console.log(p1.__proto__.constructor); // => Person(){}
    
    console.log(p1.__proto__ === Person.prototype); // true
    
  • 当一个对象在查找一个属性时,自身没有,就会根据 __proto__ 属性向他的原型中查找,如果都没有,则向它的的原型的原型进行查找,直到查到 Object.prototype.__proto__ 为 null,这样也就形成了原型链;

     let arr = []
    console.log(Array.prototype.__proto__); // Object
    console.log(Array.prototype.__proto__.__proto__); // null
    
    function Person(name) {
      this.name = name
    }
    let p1 = new Person()
    
    console.log(Person.prototype.__proto__); // Object
    console.log(Person.prototype.__proto__.__proto__); // null
    

__proto__

  • 通过 __proto__ 得到原型对象; ES6 推出后,推荐用 Object.getPrototypeOf() 方法来获取对象的原型;

    let arr = []
    
    console.log(Object.getPrototypeOf(arr));
    console.log(Object.getPrototypeOf(arr) === Array.prototype); // true
    

作用

  • 拓展自定义对象和内置对象的功能;给构造函数的prototype添加属性和方法,所有实例对象都可以使;(实例对象)

    eg: 封装 trim() 方法,解决兼容问题;

    String.prototype.trim = function() {
        return this.replace(/^\s+/, "").replace(/\s+$/, "");
        // return this.replace(/(^\s+)|(\s+$)/g,"")
    }
    
  • 用作继承 (给构造函数的prototype重新赋值为另一个构造函数的实例,用于继承;(构造函数本身))