js 原型链

一、关于 __proto__ 和 prototype 

1、__proto__  即 [[Prototype]],是对象的属性,指向对象的原型,是许多浏览器实现的非标准属性

  从ES6开始,[[Prototype]] 可以通过 Object.getPrototypeOf(obj) 和 Object.setPrototyeOf(obj)  ES2017 (ES8)访问器来访问,返回值是给定对象的原型,若没有,则返回 null

2、prototype 是 Function 的属性,构造函数所创建的 实例对象的 __proto__ 指向 构造函数的 prototype 属性(不严谨,看二.4)

二、创建对象的几种方式以及相应的原型链

1、使用{}语法创建对象

  

  i、obj 继承了 Object.prototype 上面所有的属性

  ii、Object.prototype 的原型为 null

  iii、总结原型链如下: obj.__proto__--> Object.prototype    Object.prototype.__proto__ --> null

2、js 本地对象,例如 数组

  var arr = [1,2,3];

  i、数组 都继承了 Array.prototype 上所有的属性

  ii、Arry.prototype 的原型为 Object.prototype

  iii、总结原型链如下:arr.__proto__ --> Array.prototype    Array.prototype.__proto__ --> Object.prototype     Object.prototype.__proto__ --> null

3、函数构造器创建对象

  

  i、a 继承 A,也继承 A 的属性,a修改自身属性,并不影响 A

  ii、函数 A 继承了 Object.prototype 上所有的属性

  iii、总结原型链如下:a.__proto__ --> A.prototype    A.prototype.__proto__--> Object.prototype    Object.prototype.__proto__ --> null

4、使用 Object.create() 创建对象 ES2017(ES8)

  

  i、使用 Object.create() 方法创建的新对象的 __proto__ 指向他的 父对象

  ii、新对象自身并没有 父对象 的属性和方法

  iii、总结原型链如下:newobj.__proto__ --> obj     obj.__proto__--> Object.prototype    Object.prototype.__proto__  --> null

  extra:    Object.create的用法

  Object.create(proto, [propertiesObject])

  propertiesObject 可选,添加到新创建对象自身的属性,及其描述

var topobj = Object.create(obj, {
   propertyName: {
       value: 'value属性值',    //属性值
       enumerable: true,    //是否可枚举
       configurable: true,    //是否可配置
       writable: true    // 属否可修改
    }
});

5、ES6 中 Class 关键字创建的对象

  

  i、这种情况下,原型链类似于 函数构造器创建的对象

  ii、总结原型链如下: p.__proto__ --> Polygon.prototype    Polygon.prototype.__proto --> Object.prototype   Object.prototype.__proto__ --> null

   

  i、s的原型链类似于上面的 p ,只是多了一层 Square

  ii、需要注意的是 Square 既有 __proto__ 属性,也有 prototype 属性,Polygon 其实也是有两个属性只是他的结果是本地代码,不能看到

  

三、检测属性的存在性

1、obj.hasOwnProperty('属性名') 检测该属性是不是 obj 自身的属性

  如果是自身的属性则返回 true;

  如果是存在于 obj 的原型链上或者是不存在,则返回 false

  需要注意的是:js 并没有保护 hasOwnProperty 属性名,因此存在该方法被改些的情况

  ES2017(ES8)检测自身的可枚举属性,可以使用 Object.keys(obj);

  ES2017(ES8)检测自身的可枚举属性的值,可以使用 Object.values(obj);

   

2、for...in 顺着原型链,循环便利可枚举属性

3、检测该属性是不是可枚举属性可以使用:obj.propertyIsEnumerable(属性名)

  他只能检测自身属性是否可枚举,并不会检测通过原型链继承的属性

  

4、不能通过属性值是否是 undefined 检测该属性是否存在,可能该属性却是存在,但是属性值为 undefined

  

  

原文地址:https://www.cnblogs.com/z-one/p/8611501.html