【JS-task05】JS中的原型链是什么?

小课堂【上海】

分享人:杨亚洲

目录

1.背景介绍

2.知识剖析

3.常见问题

4.解决方案

5.编码实战

6.扩展思考

7.参考文献

8.更多提问

1.背景介绍

1.构造函数

构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象。每个构造函数都有prototype(原型)属性。

2.原型模式

每个函数都有prototype(原型)属性,这个属性是一个指针,指向一个对象,这个对象的用途是包含特定类型的所有实例共享的属性和方法,即这个原型对象是用来给实例共享属性和方法的。 而同样的构造函数的原型对象上也有一个指针(constructor构造函数),指向构造函数本身。

3.实例对象

实例对象是通过new操作符+构造函数的形式,生成的对象。实例对象里面有一个内部属性[[prototype]],指向构造函数的原型对象。 先搞清楚这三者之间的关系吧

4._proto_的指向

_proto_的指向是根据创建该对象的创建方式来区分的。现阶段主要有3种。

a、字面量的形式

b、构造函数模式

c、Object.create()

原型链

我们知道构造函数里面有一个属性是prototype,这个属性是一个指针指向构造函数的原型对象,而原型对象里面 同样有一个指针(constructor),指向原型对象。而对构造函数的实来说,它有一个内部指针[[prototype]]指向构造函数 的原型对象。如果这个原型对象是另外一个构造函数的实例,那么此时原型对象又包含一个内部指针[[prototype]]指向 另一个构造函数的原型对象,如此层层递进,就构成的实例与原型的链条,也就是所谓的原型链

2.知识剖析

构造函数

构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象。 即为对象变量赋初始值。每个构造函数的实例都将共享构造函数的初始值。 构造函数的出现是为了解决使用Object构造函数和字面量表示法不方便创建大量重复对象的问题。

传统创建对象实例的方法


                    var person={
                                name:'张女士',
                                age:'80',
                                gender:'女'
                                };
                    console.log(person)
            

这个方法如果用于创建大量相同属性和方法的对象时,会产生大量重复代码

构造函数的方法


                //构造函数方法创建对象实例
                function Person(name,age,gender) {
                   this.name=name;
                   this.age=age;
                   this.gender=gender;
                   this.say=function () {
                   alert(this.name)
                    }
                }
                var person1=new Person('钟女士',80,'女');
                var person2=new Person('张女士',80,'女');
                console.log(person2)
                console.log(person1)
            

原型模式

使用构造函数的问题是,每个方法都要在每个实例上重新创建一遍,即在构造函数的不同实例上的同名函数是不相等的。而我们创建每个构造函数都有一个prototype(原型)属性,这个属性是个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法,我们使用这个原型对象来共享实例的属性和方法的模式就叫原型模式


                    //原型模式创建对象
                    function Person(){
                    }
                    Person.prototype.name='钟女士';
                    Person.prototype.age=80;
                    Person.prototype.gender='女';
                    var person1= new Person();
                    console.log(person1)
                    //简写原型模式
                    Person.prototype={
                    constructor:Person
                    name:'钟女士',
                    age:80,
                    gender:'女'
                    }
                

注:每个原型对象都有constructor属性,由于简写模式重写了默认的prototype对象,所以constructor也会被重新定义,不再指向他的构造函数,所以可以自己写一个constructor属性指向他的构造函数

原型链

每个构造函数都有原型对象,每个构造函数实例都包含一个指向原型对象的内部指针(__proto__),如果我们让第一个构造函数的原型对象等于第二个构造函数的实例,结果第一个构造函数的原型对象将包含一个指向第二个原型对象的指针,再然第三个原型对象等于第一个构造函数的实例,这样第三个原型对象也将包含指向第一个原型对象的指针,以此类推,就够成了实例于原型的链条,这就是原型链的基本概念


                        function One(){
                        }
                        function Two(){
                        }
                        function Three(){
                        }
                        Two.prototype=new One();
                        Three.prototype=new Two();
                        var three=new Three();
                        console.log(three);
                        console.log(three.__proto__===Three.prototype) //true
                        console.log(three.__proto__.__proto__===Two.prototype) //true   
                        console.log(three.__proto__.__proto__.__proto__===One.prototype)  //true
                        console.log(three.__proto__.__proto__.__proto__.__proto__===Object.prototype)  //true
             

3.常见问题

若想访问一个对象的原型,应该使用什么方法?

4.解决办法

在对象实例中,访问对象原型的方法

1、使用_proto_属性

此属性是浏览器支持的一个属性,并不是ECMAScript里的属性

2.Object.getPrototypeOf

3.使用constructor.prototype的方法

对于不支持_proto_的浏览器,可以使用constructor,访问到对象的构造函数,在用prototype访问到原型

在构造函数中,访问对象原型的方法

1.使用prototype属性

6、扩展思考

Function 也是构造函数? 所以Function.__proto__指向Function.prototype?

7、参考文献:

参考一: JavaScript高级程序设计

参考二: 作用域与事件

8、更多提问

谢谢大家

制作人:杨亚洲