一、关于 __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