原型、原型链

103 阅读2分钟

一、什么是原型和原型链?

首先我们知道JS中对象分为函数对象普通对象,其中所以对象都有_proto_,但是只有函数对象才具有prototype。

1.原型

①所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象,constructor和__proto__,constructor表示对象是由哪个构造函数创建的比如下面的test.constructor ==Test

②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象

③所有引用类型的__proto__属性指向它构造函数的prototype,也就是对象的__proto__保存着该对象的prototype

举例:

var a = [0,1,2];
a.__proto__ === Array.prototype; // true

2.原型链

当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。

举例:

         function People(age, name) {
            this.age = age
            this.name = name

        }
        const person1 = new People(24, '流小枫')
        console.log(person1.age); //24
        console.log(person1.name); //'流小枫'
        console.log(person1.height); //undefined
        console.log(person1.__proto__ === People.prototype); //true,证实了上面的“对象的__proto__保存着该对象的prototype”

我们为了证实person1.proto === People.prototype,还可以这样(第一次打印):

  function People(age, name) {
            this.age = age
            this.name = name

        }
        const person1 = new People(24, '流小枫')
        console.log(person1.__proto__ === People.prototype, ); //true,对象的__proto__保存着该对象的prototype
        console.log(person1.__proto__); //第一次打印

第一次打印结果:

image.png

第二次打印:

 function People(age, name) {
            this.age = age
            this.name = name

        }
        const person1 = new People(24, '流小枫')
        console.log(person1.__proto__ === People.prototype, ); //true,对象的__proto__保存着该对象的prototype
        People.prototype.height = 180
        console.log(person1.__proto__); //第二次打印
        

第二次打印打印结果:

image.png

通过上述例子可以证实person1.proto === People.prototype

在person1中查找某个元素时,会执行下面的步骤:

image.png

访问链路为:

image.png

我们通过一个例子来解释一下:


  function Test() {
            this.a = 1
        }
        const test = new Test()
        console.log(test);
        Test.prototype.b = 2
        console.log(Test.prototype.__proto__ === Object.prototype); //true
        console.log(Object.prototype.__proto__); //null,Object没有__proto__
        Object.prototype.c = 3 //因为Test.prototype.__proto__ ===Object .prototype
        console.log('------------------------------------------');

        console.log(test.a);
        console.log(test.b);
        console.log(test.c);

打印结果:

image.png

从这里我们可以看见查找属性是一层一层的查找,这也叫原型继承

①一直往上层查找,直到到null还没有找到,则返回undefined

②Object.prototype.proto === null

③所有从原型或更高级原型中的得到、执行的方法,其中的this在执行时,指向当前这个触发事件执行的对象

3.判断对象是否存在该属性

判断对象本身是否存在该属性(hasOwnProperty())和原型链上是否存在该属性(属性名 in 对象)

 function Test() {
            this.a = 1
        }
        const test = new Test()
        Test.prototype.b = 2
        Object.prototype.c = 3

        // hasOwnProperty(),用来判断对象本身是否含有这个属性
        console.log(test.hasOwnProperty('a')); //true
        console.log(test.hasOwnProperty('b')); //false
        console.log(test.hasOwnProperty('c')); //false

        console.log('——————————————————————————————————————');
        //属性名 in 对象,来判断原型链上是否有这个属性
        console.log('a' in test);
        console.log('b' in test);
        console.log('c' in test);