【JavaScript】JS原型链

前言

prototype

在 JavaScript 中,原型也是一个对象,通过原型可以实现对象的属性继承。
JavaScript 的对象中(null除外)都包含了一个"prototype"内部属性,这个属性所对应的就是该对象的原型。"prototype"作为对象的内部属性,是不能被直接访问的。

function Person() { }
// prototype是函数才会有的属性
Person.prototype.name = 'Kevin';
let person1 = new Person();
let person2 = new Person();
console.log(person1.name) // Kevin
console.log(person2.name) // Kevin

在这里插入图片描述

proto

每一个JavaScript对象(除了 null )都具有的一个属性,叫proto,这个属性会指向该对象的原型。

function Person() { }
let will = new Person();
console.log(person.__proto__ === Person.prototype); // true

在这里插入图片描述

constructor

每个实例原型都有一个 constructor 属性,指向关联的构造函数

function Person() { }
console.log(Person === Person.prototype.constructor); // true
console.log(person.__proto__ == Person.prototype) // true

在这里插入图片描述

实例分析:

   function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    let will = new Person("Will", 28);

Step1: 查看对象will的原型

console.log('Step-->1: 查看对象will的原型')
console.info("will.__proto__ ===>", will.__proto__); 
console.info('will.__proto__ === Person.prototype ===>',will.__proto__ === Person.prototype) // true
console.info("will.constructor ===>", will.constructor) 

在这里插入图片描述

结果分析:

  • 所有实例的原型引用的是函数的 prototype 属性。了解了构造函数的 prototype 属性之后。
  • will 对象本身没有"constructor"这个属性,但是通过原型链查找:will.__proto__,找到原型Person.prototpye的 "constructor"属性。

Step2: Person.prototype的原型

console.log('Step-->2: 查看Person.prototype的原型')
console.info('Person.prototype ===>',Person.prototype)
console.info('Person.prototype.__proto__ ===>',Person.prototype.__proto__)
console.log('Person.prototype.__proto__ === Object.prototype ===>',Person.prototype.__proto__ === Object.prototype);
console.info('Person.prototype.constructor ===>',Person.prototype.constructor)
console.info('Person.prototype.constructor === Person ===>',Person.prototype.constructor === Person) // true

在这里插入图片描述

结果分析

  • 当通过Person.prototype.__proto__语句获取will 对象原型的原型时候,将得到Object.prototype。所有对象的原型都将追溯到Object.prototype对象。
  • 对于原型对象Person.prototype.constructor对应 Person(){}函数本身。

Step3: 查看对象 Object 的原型

// Step-->3: 查看对象 Object 的原型
console.log('Step-->3: 查看对象 Object 的原型')
console.log('typeof Object ===>',typeof Object);
console.log('Object ===>',Object);
console.log('Object.prototype ===>',Object.prototype);
console.log('Object.prototype.__proto__ ===>',Object.prototype.__proto__);
console.log('Object.prototype.constructor ===>',Object.prototype.constructor);

在这里插入图片描述
结果分析

  • Object对象本身是一个函数对象,就肯定会有prototype属性,可以看到Object.prototype的值就是Object {}这个原型对象。
  • 访问Object.prototype对象的constructor属性的时候,得到Obejct函数。
  • 通过Object.prototype.proto获取Object原型的原型的时候,将会得到"null",也就是说"Object {}"原型对象就是原型链的终点。

Step4: 查看对象Function的原型

// Step-->4: 查看对象Function的原型
console.log('Step-->4: 查看对象Function的原型')
console.log('Person.__proto__ === Function.prototype ===>',Person.__proto__ === Function.prototype);
console.log('Person.constructor === Function ===>',Person.constructor === Function)
console.log('typeof Function ===>',typeof Function);
console.log('Function ===>',Function);
console.log('Function.prototype ===>',Function.prototype);
console.log('Function.prototype.__proto__ ===>',Function.prototype.__proto__);
console.log('Function.prototype.constructor ===>',Function.prototype.constructor);

在这里插入图片描述
结果分析

  • 在JavaScript中有个Function对象(类似Object),这个对象本身是个函数;所有的函数(包括Function,Object)的原型(proto)都是"Function.prototype"。
  • Function对象作为一个函数,有prototype属性,该属性将对应function () {...}对象。
  • Function对象作为一个对象,就有proto属性,对应Function.prototype,即,Function.__proto__ === Function.prototype
  • 对于Function的原型对象Function.prototype,该原型对象的proto属性将对应"Object {}"

小结

综上:构造函数、原型对象、实例的关系可以参照下图:
在这里插入图片描述

__proto__和prototype

区别:

  • 对于所有的对象,都有__proto__属性,这个属性对应该对象的原型
  • 对于函数对象,除了__proto__属性之外,还有__prototype__属性,当一个函数被用作构造函数来创建实例时,该函数的prototype属性值将被作为原型赋值给所有对象实例,会被赋值给该函数创建的对象的__proto__属性
  • 所有的原型对象都有constructor属性,该属性对应创建所有指向该原型的实例的构造函数
  • 函数对象和原型对象通过prototypeconstructor属性进行相互关联
  • 因为每个对象和原型都有原型,对象的原型指向对象的父,而父的原型又指向父的父,这种原型层层连接起来的就构成了原型链

常用方法

原型判断:

  • 获得原型:Object.getPrototypeOf(对象);
  • 构造函数检测原型:构造函数原型.isPrototypeOf(对象),返回布尔值
    console.log('Object.getPrototypeOf(will) === Person.prototype ===>',Object.getPrototypeOf(will) === Person.prototype)
    console.log('Person.prototype.isPrototypeOf(will)  ===>',Person.prototype.isPrototypeOf(will))

在这里插入图片描述

属性枚举

  • for…in可以输出原型中可枚举的属性,不仅仅是私有属性;

  • hasOwnProperty():是Object.prototype的一个方法:能判断一个对象是否包含自定义属性而不是原型链上的属性(JavaScript 中唯一一个处理属性但是不查找原型链的函数)。

  • Object.getOwnPropertyNames(对象名):方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。

  • 可枚举的私有属性的名称:Object.keys

   Person.prototype.getInfo = function () {
      console.log(this.name + " is " + this.age + " years old");
    };
    let will = new Person("Will", 28);
    
    for (let attr in will) {
      console.log('自定义属性和原型链属性',attr); // name // age // getInfo
    }
   
    for(let attr in will) {
      if (will.hasOwnProperty(attr)) {
        console.log('自定义属性',attr);// name // age
      }
    }

    console.log('Object.getOwnPropertyNames',Object.getOwnPropertyNames(will))
    console.log('Object.keys',Object.keys(will))

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值