# object
- for...in 返回所有的可遍历属性,继承的➕自身的,
- JavaScript 的早期版本,for...in循环是基于in运算符的。我们知道,in运算符不管某个属性是对象自身的还是继承的,都会返回true
- toString不是obj对象自身的属性,但是in运算符也返回true,这导致了toString属性也会被for...in循环遍历。
- 这显然不太合理,后来就引入了“可遍历性”这个概念。只有可遍历的属性,才会被for...in循环遍历,同时还规定toString这一类实例对象继承的原生属性,都是不可遍历的,这样就保证了for...in循环的可用性
- 如果一个属性的enumerable为false,下面三个操作不会取到该属性。
- for..in循环
- Object.keys方法
- JSON.stringify方法
# Object 的静态方法
Object.keys(), 返回该对象自身可枚举的属性, 故数组的不可枚举属性length无法取到
Object.getOwnPropertyNames(), 返回自身的所有属性,包括不可枚举属性,故数组的不可枚举属性length可以取到
Object.getOwnPropertySymbols(),返回自身所有的Symbol属性
Object.create():该方法可以指定原型对象和属性,返回一个新的对象
Object.getPrototypeOf():获取对象的Prototype对象
Object.getOwnPropertyDescriptor():获取某个属性的描述对象。
Object.defineProperty():通过描述对象,定义某个属性。
Object.defineProperties(): 通过描述对象,定义多个属性
# Object 的实例方法
- Object.prototype.valueOf():返回当前对象对应的值。
- Object.prototype.toString():返回当前对象对应的类型字符串。
- 数组、字符串、函数、Date 对象都分别部署了自定义的toString方法,覆盖了Object.prototype.toString方法
- [1, 2, 3].toString() // "1,2,3"
- '123'.toString() // "123"
- (function () { return 123; }).toString() // "function () { // return 123; // }"
- (new Date()).toString() // "Tue May 10 2016 09:11:31 GMT+0800 (CST)"
- toString() 的应用:判断数据类型
let type = o => {
return Object.prototype.toString.call(o).slice(8,-1)
}
['Null',
'Undefined',
'Object',
'Array',
'String',
'Number',
'Boolean',
'Function',
'RegExp'
].forEach(t=>{
type['is'+t] = function(o){
return type(o) === t
}
})
console.log(type.isNumber(123))
- Object.prototype.hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性
- Object.prototype.isPrototypeOf():判断当前对象是否为另一个对象的原型
- Object.prototype.propertyIsEnumerable():判断某个属性是否可枚举
# 对象的可枚举属性
- Object.keys(),返回对象自身的所有可枚举属性
- Object.values(),返回对象自身的所有可枚举属性值
- for...in ,循环遍历对象的可枚举属性,包括原型链上的可枚举属性,可使用hasOwnProperty()剔除掉原型链上的可枚举属性
- 只有Object.getOwnPropertyNames(),包含不可枚举属性
- 规定toString这一类实例对象继承的原生属性,都是不可遍历的
- for...in循环包括继承的属性,Object.keys方法不包括继承的属性。如果需要获取对象自身的所有属性,不管是否可遍历,可以使用Object.getOwnPropertyNames方法
- 引入“可枚举”(enumerable)这个概念的最初目的,就是让某些属性可以规避掉for...in操作,不然所有内部属性和方法都会被遍历到。比如,对象原型的toString方法,以及数组的length属性,就通过“可枚举性”,从而避免被for...in遍历到
# 属性描述对象
- 属性描述对象提供6个元属性
- value是该属性的属性值,默认为undefined
- writable表示属性值(value)是否可写,默认为true
- enumerable是一个布尔值,表示该属性是否可遍历,默认为true
- configurable是一个布尔值,表示可配置性,默认为true,如果设为false,将阻止某些操作改写该属性,比如无法删除该属性
- get是一个函数,表示该属性的取值函数(getter),默认为undefined
- set是一个函数,表示该属性的存值函数(setter),默认为undefined
#
- 1.属性是否存在:in运算符,它不能识别哪些属性是对象自身的,哪些属性是继承的,需要结合对象的hasOwnProperty方法判断一下,是否为对象自身的属性
- 2.属性的遍历:for...in 循环,
- 它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性。
- 它不仅遍历对象自身的属性,还遍历继承的属性
# es6
- ES6 允许字面量定义对象时,用表达式作为对象的属性名,即把表达式放在方括号内
# es6对象的新增方法
- Object.is()
- Object.assign()
- Object.getOwnPropertyDescriptors()
- __proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf()
- Object.keys(),Object.values(),Object.entries()
- Object.fromEntries()
Object.defineProperty(Object, 'is', {
value: function(x,y){
if(x===y){
// 针对+0 不等于 -0的情况
return x!==0||1/x===1/y
}
//针对NaN
return x!==x && y!==y
},
configurable: true,
enumerable: false,
writable: true
})
function getOwnPropertyDescriptors(obj){
let ret = {}
for(let key of Object.keys(obj)){
ret[key] = Object.getOwnPropertyDescriptor(obj, key)
}
return ret
}
const shallowClone = obj => Object.create(Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj))