原型

166 阅读2分钟

原型

每一个JS对象(null除外)都和一个对象相关联,这个对象就是原型,每一个对象都从原型继承属性
js对象内部包含[[prorotype]]指向原型对象,可以通过__proto__访问
可以通过Object.getPrototypeOf(obj) 来获取对象的原型属性
或者通过isPrototypeOf()来判断某个对象是否为另外一个对象的原型

        let obj = {};
        console.log(Object.getPrototypeOf(obj) === Object.prototype); //true
        console.log(Object.prototype.isPrototypeOf(obj)); //true
        let arr = new Array();
        console.log(Object.getPrototypeOf(arr) === Array.prototype); //true
        let p = { a: 1 };
        p1 = Object.create(p);
        console.log(Object.getPrototypeOf(p1) === p); //true

设置对象的原型属性

proto

直接操作私有属性,不推荐

        let a = { x: 1 };
        let b = {
          __proto__: a,
        };
        console.log(Object.getPrototypeOf(b) === a); //true

Object.setPrototypeOf(a,b)

两个参数,第一个参数为要设置原型的对象,第二个为设置对象的新原型,如果第二个参数是NULL或者不是对象的话,会报错

       let a = { x: 1 };
       let b = {};
       Object.setPrototypeOf(b, a);
      console.log(Object.getPrototypeOf(b) === a); //true

super

es6新增的一个关键字 super ,可以在类中使用,对象中的super关键字指向该对象的原型(由于super不能单独使用,所以无法打印)

      let obj1 = {
        fn1() {
          return "fn1";
        },
      };
      let obj2 = {
        fn2() {
          return super.fn1();
        },
      };
      Object.setPrototypeOf(obj2, obj1);
      console.log(obj2.fn2()) //fn1

原型链

当我们访问一个对象的属性或者方法时,会在对象本身找,如果没有则会到他的原型对象上找,如果 还没有就回到原型对象的原型对象上去找,找到则返回对应的值,如果直到原型对象为NULL,则返回undefined

        function Person() {}
        Person.prototype.name = "jerry";
        Person.prototype.sayName = function () {
          console.log(this.name);
        };
        let person1 = new Person();
        let person2 = new Person();
        person1.sayName();
        console.log(person1.sayName === person2.sayName); //true
        console.log(person1.sayName === Person.prototype.sayName); //true
        console.log(Person.prototype.isPrototypeOf(person1)); //true

原型链示意图

(自身普通属性prototype指向Person.prototype(只有函数function有,其他为undefined),原型属性[[prototype]] 指向 Function.prorotype)

实践中的原型

1 查询属性会遍历原型链,有一定的性能问题,要注意代码中的原型链长度,并在必要时分解,以避免潜在的性能问题
2 原型上的属性会被所有实例共享,如果属性值是对象类型,则某个实例更改之后会影响其他实例, 原始类型则不会

      function Person() {}
      Person.prototype = {
        name: "tom",
        book: [],
      };
      let p1 = new Person();
      let p2 = new Person();
      p1.name = "jerry";
      p1.book.push("tom and jerry"); //tom
      console.log(p2.name, p2.book); //tom and jerry

这篇文章到这里就结束了,如有错误希望大佬指出