通过阅读MDN,总结了一些关于Object的方法
-
Object.defineProperty(obj, prop, descriptor)
- 该方法会直接在一个对象上(obj)定义一个新属性(prop),或者修改一个对象的现有属性,并返回此对象。
- params : obj - 要传入的对象 ,prop - 要定义或修改的属性 ,descriptor - 要定义或修改属性的描述符
- 关于descriptor中的get 和 set 总结 - 访问属性时调用get,属性修改时调用set
-
Object.defineProperty(obj, prop, descriptor)
关于descriptor(描述符):
- configurable:
当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
默认为 false。
- enumerable:
enumerable定义了对象的属性是否可以在for...in循环和Object.keys()中被枚举。
默认为 false。
- value:
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。
默认为 undefined。
- writable:
当 writable 属性设置为 false 时,该属性被称为“不可写的”。它不能被重新赋值。
默认为 false。
- get
属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。
默认为 undefined。
- set
属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。
默认为 undefined。
下面以一道常见的面试题来当作应用:
var _default = 0;
Object.defineProperty(window,'a',{
get(){
return ++ _default; //get函数的返回值作为该属性的值!
}
})
//使浏览器打印 'you win '
if (a === 1 && a ===2 && a === 3) {
console.log('you win')
console.log(window.a)
}
-
Object.assign(target,...sources)
- 该方法将...sources(即可以是多个对象源)中的可枚举属性添加到target(目标对象)中。
-
Object.assign(target,...sources)
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);// expected output: Object { a: 1, b: 4, c: 5 }
细节点1:继承属性和不可枚举属性是不能拷贝的
const obj = Object.create({foo: 1}, { // foo 是个继承属性。
bar: {
value: 2 // bar 是个不可枚举属性。
},
baz: {
value: 3,
enumerable: true // baz 是个自身可枚举属性。
}
});
const copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }
细节点2:原始类型会被包装成对象
const v1 = "abc";
const v2 = true;
const v3 = 10;
const v4 = Symbol("foo")
const obj = Object.assign({}, v1, null, v2, undefined, v3, v4);
// 原始类型会被包装,null 和 undefined 会被忽略。
// 注意,只有字符串的包装对象才可能有自身可枚举属性。
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
-
Object.create(proto,[propertiesObject])
- 方法创建一个新对象,使用现有的对象来提供新创建的对象的__ proto__。
- params : proto- 新创建对象的原型对象,[propertiesObject] - 可选,需要传入一个对象,参考Object.defineProperty中的描述符
- return : 一个新对象,带着指定的原型对象和属性。
-
Object.create(proto,[propertiesObject])
我们可以使用该方法,实现一个兼容所有浏览器的继承方法(即寄生组合式继承)。
function Parent(){
this.x = 100;
}
parent.prototype.getX = function(){
return this.x;
}
function Child(){
//将parent中this.xxx的私有属性拿到
parent.call(this);
this.y = 200;
}
//创建一个空对象x,并且把[OBJECT](这个值需要是一个对象)作为新对象的原型指向
Child.prototype = Object.create(parent.prototype)
Child.prototype.constructor = child;
Child.prototype.getY = function(){
}
-
Object.entries(obj)
- 该方法将对象转换为数组,数组中存储的是该对象可枚举的属性及其值
-
Object.entries(obj)
function Test() {
this.a = 1;
this.b = 2
}
Test.prototype.c = 3;
const test = new Test();
for (let k in test) {
console.log(k, test[k]);
}
// for in 会把遍历对象的原型上的自定义属性也遍历出来
// 将对象转换成数组的形式 - >可迭代 [['a',1],['b',2]]
const testArr = Object.entries(test);
for (let [k, val] of testArr) {
console.log(k, val)
}
与之相对的方法为Object.fromEntries(),该方法把键值对列表转换为对象,值得注意的是在将对象用Object.entries()转换后,再用Object.fromEntires()转换回来,和原对象用的不是同一个引用地址
-
- Object.freeze(obj)
- 冻结的对象不可修改、不可删除、不可添加属性,冻结后的原型不可修改。
- 特别注意不论是Object.freeze()、Object.preventExtensions()、Objext.seal(),对对象的操作都是对属性的第一层的操作,即浅冻结,上面所说冻结后的原型不可修改指的是不可重新赋值一个新的引用地址,我们是可以对原型上的属性进行操作的。
- Object.defineProperty()同样也不能对冻结后的对象进行操作
- 方法返回值与参数obj是同一引用地址
MDN中也有写了对象的深度冻结
Object.deepFreeze = function (o) {
// Object.keys() //不能拿到不能枚举的属性
var _key = Object.getOwnPropertyNames(o)
if (_key.length) {
_key.forEach(function (k) {
var _value = o[k];
if (typeof _value === 'object' && _value !== null) {
Object.deepFreeze(_value)
}
})
}
return Object.freeze(o);
}
-
Objext.seal(obj)
- 该方法对obj进行密封(浅密封),obj被密封后,可修改,不可删除,不可扩展。
- 该方法返回的是原对象的引用地址
-
Objext.seal(obj)
-
7 . Object.preventExtensions()
- 返回的obj 可修改 可删除 不可扩展
- Object.defineProperty() 也不能给其扩展
-
对比 freeze seal preventExtensions
- freeze 不可修改 不可删除 不可扩展
- seal 可修改 不可删除 不可扩展
- preventExtensions 可修改 可删除 不可扩展
- 当obj = {} 并且 Object.preventExtensions(obj),Object.isFrozen(obj) Object.isSealed(obj)均返回true,原因是 当是空对象且又不可扩展时 也满足它们的判断条件
-
8 . Object.keys(obj)
- 方法会返回一个由obj自身可枚举属性组成的数组,数组中属性的排列顺序和正常循环遍历对象时的顺序一致。
-
9 . Object.getOwnPropertyNames(obj)
- 返回一个数组,该数组对元素是 obj自身拥有的枚举或不可枚举属性名称字符串。 数组中枚举属性的顺序与通过 for...in 循环迭代该对象属性时一致。数组中不可枚举属性的顺序未定义。
-
10 . Object.prototype.hasOwnProperty(obj)
- 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。