javascript 原型链

我们每创建一个函数都会有一个 prototype属性,该属性是一个对象,原型对象中存在一个 constructor 属性,该属性值指向原函数

function Person() {
}
console.log(Person.prototype);

控制台输出内容:

每个通过构造函数创建的实例默认都指向了这个原型对象 prototype

        function Person() {}
        Person.prototype.name = 'Tom'
        Person.prototype.sayName = function () {
            console.log(this.name);
        }
        const person1 = new Person()
        const person2 = new Person()    
        //通过构造函数创建的实例内部中,有一个属性指向原型对象
        console.log(person1.__proto__ === Person.prototype); //true
        console.log(person2.__proto__ === Person.prototype); //true
        也可以通过ES5 新增的一个方法来验证
        //Object.getPrototypeOf()  方法返回指定对象的原型(内部[[Prototype]]属性的值)。MDN
        console.log(Object.getPrototypeOf(person1) === Person.prototype); //true
        console.log(Object.getPrototypeOf(person1) === Person.prototype); //true

prototype所指向的那个对象,为通过构造函数创建的实例,提供共享属性和方法的功能,
示例1:

        function Person() {}
        Person.prototype.name = 'Tom'
        Person.prototype.sayName = function () {
            console.log(this.name);
        }
        const person1 = new Person()
        const person2 = new Person()
        //实例在获取一个方法或属性的时候。会先在自身寻找该属性或方法,如果自身不存在,会继续向上查找原型对象,找到后返回,如果没有找到则是 undefined
        function Person() {}
        const person1 = new Person()
        person1.sayName() //Tom
        person2.sayName() //Tom
        console.log(person1.sayName === person2.sayName); //true

示例2:

        function Person (){}
        Person.prototype = {
              name:"Tom",
              sayName: function(){
                    log(this.name)
              }
        }
        const person1 = new Person()
        person2.sayName() //Tom

要注意的地方

代码段 A:

        function Person() {}
        Person.prototype = {
            name: "Tom",
            sayHi: function () {
                console.log("Hi --- " + this.name);
            }
        }
        const person1 = new Person()
        person1.sayHi() // Hi --- Tom

这段代码中的实例对象,是在原型添加新方法和属性之后创建的,它可以访问到原型中的方法和属性

下面这段代码中的实例,也是在原型中添加新方法和属性之前创建的,但是它却访问不到原型中定义的属性和方法
代码段 B:

        function Person() {}
        const person1 = new Person()
        Person.prototype = {
            name:"Tom",
            sayHi: function () {
                console.log("Hi --- " + this.name);
            }
        }
        person1.sayHi() //报错 Uncaught TypeError: person1.sayHi is not a function

原因就在于, prototype 是一个指针,指针中存放的是原型对象的地址,这里假如存放的地址为 1000H ,那么在new实例的时候,实例对象中也包含一个指针,指向 prototype这个指针,这有点像C语言中的多级指针。在代码段 B中,new实例的时候,实例中的指针指向 prototype 指针, prototype 指针中存放的原型地址为 1000H,当代码运行到重写原型那一行,这时,原型对象的地址已经改变了 ,这里假如它改变的地址为 1001H,它里面存放了 name 属性 和 sayHi 方法。我们在之后,访问sayHi这个方法时,访问的还是之前 prototype 指针中存放的 1000H 这个地址中的原型对象。

下图来自 js 高程 6.2 --157 页

原文地址:https://www.cnblogs.com/freedomweb/p/12963256.html