Object方法总结(JS)
1、对象的合并——Object.assign()
语法: Object.assign(target,…sources)
参数说明:target:目标对象; …sources:源对象。
① 后面对象会覆盖前面对象
② 并且会使target对象也改变(eg: 下面a的打印)
const a = {
name: "lisa",
age: 12,
color: "red",
address: "shanghai"
};
const b = {
sex: 'girl',
age: 11,
name: "lisa",
};
let c = Object.assign({ address: "beijing" }, a, b);
console.log(c); //结果为{address: 'shanghai', name: 'lisa', age: 11, color: 'red', sex: 'girl'}
console.log(a); //{name: 'lisa', age: 12, color: 'red', address: 'shanghai'}
更深一步:Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关 getter 和 setter。因此,它分配属性,而不仅仅是复制或定义新的属性。如果合并源包含getter,这可能使其不适合将新属性合并到原型中。为了将属性定义(包括其可枚举性)复制到原型,应使用Object.getOwnPropertyDescriptor()和Object.defineProperty() 。
在出现错误的情况下,例如,如果属性不可写,会引发TypeError,如果在引发错误之前添加了任何属性,则可以更改target对象。
注意,Object.assign 不会跳过那些值为 null 或 undefined 的源对象。
2、获取对象所有属性——Object.key()
返回结果为[ ],Object.key()遍历可枚举的属性,只包含对象本身可枚举属性,不包含原型链可枚举属性。
① 传入一个对象,返回包含对象可枚举的属性
const obj = {
name: 'lisa',
age: 12,
say: function() {
alert("Hello World");
}
}
console.log(Object.keys(obj)); // ['name', 'age', 'say']
② 传入一个字符串,返回字符串索引值
const myStr="Hello World"
console.log(Object.keys(myStr));
//打印结果为["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
③ 传入一个数组,返回索引值
const arr=['a','b','c'];
console.log(Object.keys(arr));
//结果为['0','1','2']
④ 构造函数,返回空数组或者属性名
function Demo(name, age) {
this.name = name;
this.age = age;
}
console.log(Object.keys(Demo));
//结果为[]是一个空数组
3、可枚举属性值——Object.values()
遍历可枚举的属性值,只包含对象本身可枚举属性值,不包含原型链可枚举属性值
Object.values()返回一个数组,其元素是在对象上找到的可枚举属性值。属性的顺序与通过手动循环对象的属性值所给出的顺序相同
const obj = {
name: "lisa",
color: "red",
age: 12
};
console.log(Object.values(obj));//结果为["lisa", "red", 12]
4、分割对象——Object.entries()
const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]
// array like object
const obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]
// string
Object.entries('abc') // [['0', 'a'], ['1', 'b'], ['2', 'c']]
Object.entries(100) // []
① 返回一个数组,其元素是与直接在object上找到的可枚举属性键值对相对应的数组。属性的顺序与通过手动循环对象的属性值所给出的顺序相同。
② 返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for…in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)。
5、在一个对象上定义一个新属性——Object.defineProperty()
Object.defineProperty(obj, prop, descriptor)
参数说明: obj: 需要被操作的目标对象
prop: 目标对象需要定义或修改的属性的名称
descriptor: 将被定义或修改的属性的描述符
//定义一个名为obj对象
let obj = new Object();
//为对象obj定义一个属性名为name,然后对name进行描述
Object.defineProperty(obj, 'name', {
configurable: false, //能否通过delete删除name属性,能否修改属性的特性,能否修改把属性修改为访问器属性
writable: true, //能否修改属性的值
enumerable: true, //该属性是否可枚举,即是否通过for...in循环或Object.keys()返回属性
value: 'lisa' //该属性对应的值
})
console.log(obj.name);
6、获取原型对象——Object.getPrototypeOf()
// 空对象的原型是Object.prototype
console.log(Object.getPrototypeOf({})===Object.prototype);
//结果为true
//Object.prototype的原型是null
console.log(Object.getPrototypeOf(Object.prototype)===null);
// 结果为true
//函数的原型是Function.prototype
function f(){}
console.log(Object.getPrototypeOf(f)===Function.prototype);
//结果为true
7、设置原型——Object.setPrototypeOf()
参数说明:第一个是现有对象,第二个是原型对象
将对象a的原型设置为对象b,因此a可以共享b的属性。
let a={age:12};
let b={name:'lisa'};
let c=Object.setPrototypeOf(a,b);//设置b为a的原型对象
console.log(c);//结果为{age:12},返回第一个参数的对象
console.log(Object.getPrototypeOf(a)===b);//结果为true
console.log(a.name);//结果为'lisa',此时对象a可以直接调用对象b中的属性
new命令可以使用Object.setPrototypeOf方法模拟如下:
let F = function() {
this.foo = "bar";
}
let f = new F();
//等同于
let f = Object.setPrototypeOf({}, F.prototype);
F.call(f);
console.log(f)
8、指定的原型对象和属性创建一个新对象——Object.create()
new和Object.create()的区别:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vz2B01lh-1642141497146)(C:\Users\huawei\AppData\Roaming\Typora\typora-user-images\image-20220113101224875.png)]
let A = {
say: function() {
console.log("我说点啥?")
}
}
//使用A作为B的原型,此时B将会拥有A的属性和方法
let B = Object.create(A);
//判断B的原型对象是不是A
console.log(Object.getPrototypeOf(B) === A); //结果为true
//B可以直接调用A的方法
B.say(); //结果为”我说点啥?“
//判断A和B的方法是不是同一个?
console.log(B.say === A.say); //结果为true
小结:Object.create方法以A对象为原型,生成了B对象,B继承了A的所有属性和方法。使用Object.create方法的时候,必须提供对象原型,即参数不能为空,或者不是对象,否则会报错。
eg:Object.create();Object.create(123)
- Object.create方法生成的新对象,动态继承了原型。在原型上添加或修改任何方法,会立刻反映在新对象之上。
let obj1 = {
p: 1
};
let obj2 = Object.create(obj1);
obj1.p = 2;//修改obj1的p属性的值
console.log(obj2.p);// 2
小结:obj2继承obj1,修改obj1会影响到obj2
- Object.create方法还可以接受第二个参数,该参数是一个属性描述对象,它所描述的对象属性,会添加到实例对象,作为该对象自身的属性
let obj = Object.create({}, {
p1: {
value:123,
enumerable:true,
configurable:true,
writable:true
},
p2:{
value:'hello',
enumerable:true,
configurable:true,
writable:true
}
});
//等同于
let obj = Object.create({});
obj.p1 = 123;
obj.p2 = 'hello';
- 第一个参数为对象,对象为函数调用之后返回新对象的原型对象,第二个参数为对象本身的实例方法(默认不能修改,不能枚举)
const obj = Object.create({a:1}, {b: {value: 2}})
obj.__proto__.a === 1 // true
obj.b = 3;
console.log(obj.b) // 2
//创建一个可写的,可枚举的,可配置的属性p
obj2 = Object.create({}, {
p: {
value: 2, // 属性值
writable: true, // 是否可以重写值
enumerable: true, //是否可枚举
configurable: true //是否可以修改以上几项配置
}
});
obj2.p = 3;
console.log(obj2.p) // 3
注意: enumerable 会影响以下
for…in 遍历包括对象原型上属性
Object.keys() 只能遍历自身属性
JSON.stringify 只能序列化自身属性
9、冻结一个对象——Object.freeze()
被冻结对象自身的所有属性都不可能以任何方式被修改。任何修改尝试都会失败,无论是静默地还是通过抛出TypeError异常(最常见但不仅限于strict mode)。
const obj1 = { name: "lisa", age: 12, color: "red" };
Object.freeze(obj1);//冻结obj1
obj1.name="coco";//修改obj1的name属性值,此时会报错,因为obj1的属性被冻结了
delete obj1.age;//报错,不能删除Obj1的属性
obj1.adress="beijing";//报错,不能添加给obj1属性
10、判断一个对象是否被冻结——Object.isFrozen()
一个对象是冻结的是指它不可扩展,所有属性都是不可配置的,且所有数据属性(即没有getter或setter组件的访问器的属性)都是不可写的。
const obj={name:"coco",age:12};
Object.freeze(obj);
console.log(Object.isFrozen(obj));//结果为true
11、对象密封——Object.seal()
密封对象是指那些不能添加新的属性,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性,但可能可以修改已有属性的值的对象。
const o2 = {b: 1}
o2.d = 2 //添加成功
const obj2 = Object.seal(o2);
obj2 === o2 //true 方法返回原对象,栈指针指向同一块内存
Object.isSealed(o2) // true
o2.b = 111 //修改b属性值成功
o2.f = 222 //静默失败,属性f没有成功添加
delete o2.b //静默失败,属性b没有成功删除
12、判断对象是否密封——Object.isSealed ()
let o = {};
Object.isSealed(o) //false
// 之后通过Object.preventExtensions方法将空对象设置为不可扩展。
Object.preventExtensions(o);
Object.isSealed(o) // true
但是如果为非空对象呢?
let o2 = {a: 1}
Object.preventExtensions(o2);
Object.isSealed(o2) // false
因为属性 a 是可配置的(configurable为true),所以不是密封的对象,修改方法如下:
let o2 = {a: 1}
Object.preventExtensions(o2);
Object.defineProperty(o2, "a", { configurable: false });
Object.isSealed(o2) //true
小结: 1.密封一个对象会让这个对象变的不能添加新属性,且所有已有属性会变的不可配置。
2.属性不可配置的效果就是属性变的不可删除,以及一个数据属性不能被重新定义成为访问器属性,或者反之。 3.但属性的值仍然可以修改。 4.尝试删除一个密封对象的属性或者将某个密封对象的属性从数据属性转换成访问器属性,结果会静默失败或抛出TypeError 异常(严格模式)
13、判断是否参数对象原型——Object.prototype.isPrototypeOf()
用于测试一个对象是否存在于另一个对象的原型链上
function Foo() {}
function Bar() {}
function Baz() {}
Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);
var baz = new Baz();
console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true
14、指定的属性是否可枚举——Object.propertyIsEnumerable()
obj.propertyIsEnumerable(prop) prop为被测试的属性名
1. 一般情况下
const o = {};
const a = [];
o.prop = 'is enumerable';
a[0] = 'is enumerable';
o.propertyIsEnumerable('prop'); // 返回 true
a.propertyIsEnumerable(0); // 返回 true
2. 浏览器内置对象
const a = ['is enumerable'];
a.propertyIsEnumerable(0); // 返回 true
a.propertyIsEnumerable('length'); // 返回 false
Math.propertyIsEnumerable('random'); // 返回 false
this.propertyIsEnumerable('Math'); // 返回 false
3. 自身属性和继承属性
(原型链上propertyIsEnumerable不被考虑)
let fn = function(){
this.prop = '123';
}
fn.prototype = { prototypeProp: true}
let o = new fn()
o.propertyIsEnumerable('prop') // true
o.propertyIsEnumerable('prototypeProp') // false
15、Object.getOwnPropertyNames()
与keys相似,但包含遍历包含不可枚举属性
let my_obj = Object.create({}, {
getFoo: {
value: function() { return this.foo; },
enumerable: false
}
});
my_obj.foo = 1;
Object.getOwnPropertyNames(my_obj).sort() // ["foo", "getFoo"]
16、是否具有指定的属性——Object.prototype.hasOwnProperty()
hasOwnProperty方法返回一个布尔值,指示对象自身属性中是否具有指定的属性,是 JavaScript 之中唯一一个处理对象属性时,不会遍历原型链的方法。
let o = {a: 1 }
o.hasOwnProperty('a') //true
o.hasOwnProperty('b') //false 对象自身没有属性b
o.hasOwnProperty('toString'); //false 不能检测对象原型链上的属性
如何遍历一个对象的所有自身属性,例子:
var buz = {
fog: 'stack'
};
for (var name in buz) {
if (buz.hasOwnProperty(name)) {
console.log("this is fog (" + name + ") for sure. Value: " + buz[name]);
}
else {
console.log(name); // toString or something else
}
}
17、在一个对象上定义一个或多个新的属性或修改现有属性——Object.defineProperties(obj, props)
参数说明:
obj: 将要被添加属性或修改属性的对象
props: 该对象的一个或多个键值对定义了将要为对象添加或修改的属性的具体配置
let obj = new Object();
Object.defineProperties(obj, {
name: {
value: '张三',
configurable: false,
writable: true,
enumerable: true
},
age: {
value: 18,
configurable: true
}
})
console.log(obj.name, obj.age) // 张三, 18
18、获取该属性的描述对象——Object.getOwnPropertyDescriptor()
let person = {
name: '张三',
age: 12
}
let des = Object.getOwnPropertyDescriptor(person, 'name');
console.log(des); // {value: "张三", writable: true, enumerable: true, configurable: true}
19、返回指定对象所有自身属性(非继承属性)的描述对象——Object.getOwnPropertyDescriptors()
var person = {
name: '张三',
age: 12
}
var des = Object.getOwnPropertyDescriptors(person);
console.log(des);
// {
// name: {
// configurable: true
// enumerable: true
// value: "张三"
// writable: true
// },
// age: {
// configurable: true
// enumerable: true
// value: 12
// writable: true
// }
// }
19、返回指定对象所有自身属性(非继承属性)的描述对象——Object.getOwnPropertyDescriptors()
var person = {
name: '张三',
age: 12
}
var des = Object.getOwnPropertyDescriptors(person);
console.log(des);
// {
// name: {
// configurable: true
// enumerable: true
// value: "张三"
// writable: true
// },
// age: {
// configurable: true
// enumerable: true
// value: 12
// writable: true
// }
// }
点击查看更多