前言
在JavaScript中,几乎所有的对象都是
Object
类型的实例,它们都会从Object.prototype
继承属性和方法。这篇文章来总结下对象都有哪些方法。
从上图我们可以看到Object的所有方法,接下来我们来了解下这些方法都是做什么的
1、Object.assign()方法:合并一个或多个对象来创建一个新的对象。
语法:Object.assign(target, obj1, obj2, ....objN);将所有可枚举属性的值从一个或多个对象复制到目标对象。它将返回目标对象。相同属性将会覆盖目标对象属性值。
let target = {a: 1},
obj1 = {a: 4, b: 2},
obj2 = {c: 3};
let response = Object.assign(target, obj1, obj2);
console.log(target) // { a: 4, b: 2, c: 3 } target改变 a = 4 是因为被覆盖了
console.log(response) // { a: 4, b: 2, c: 3 }
2、Object.create()方法:创建一个新对象
语法:Object.create(obj);使用现有的对象来作为新创建的对象的__proto__
let Dog = {
name : '小黄',
say: function () { console.log('这个小狗名字叫' + this.name);}
}
let dog = Object.create(Dog);
dog.name = '小黑';
dog.say(); // 这个小狗名字叫小黑
// create方法还可接受第二个参数 propertiesObject 为新创建的对象添加指定的属性值和对应的属性描述符 感兴趣的可以研究下
3、Object.defineProperties()方法:方法直接在一个对象上定义一个或多个新的属性或修改现有属性,并返回该对象。
语法:Object.defineProperties(obj, props) // obj:目标对象 props:要定义其可枚举属性或修改的属性描述符的对象。
属性描述符
对象中存在的属性描述符主要有两种:数据描述符和访问器描述符、通俗的来讲就是
数据属性和访问器属性/存取描述符
。下面来看一下这俩种属性都有哪些键值。
数据属性的键值
1、configurable
表示能否通过delete删除此属性,能否修改属性的类型。默认为
false
2、enumerable
表示该属性是否可枚举,是否可以通过for-in循环或Object.keys()返回。 默认为
false
3、value
该属性的属性值。默认为
undefined
4、writable
能否修改属性值。 默认为
false
访问器属性的键值
和数据属性一样都有configurable、enumerable这俩个键值
1、configurable
表示能否通过delete删除此属性,能否修改属性的类型。默认为
false
2、enumerable
表示该属性是否可枚举,是否可以通过for-in循环或Object.keys()返回。 默认为
false
3、get
给属性提供 getter 方法
访问对象属性时调用的函数,返回当前属性值
,如果没有 getter 则为 undefined 默认为undefined
4、set
给属性提供 setter 方法
给对象属性设置值时调用的函数
,如果没有 setter 则为 undefined。默认为undefined
下面我们来看下用 Object.defineProperties() 方法来定义属性
var 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
delete obj.name;
delete obj.age;
console.log(obj.name, obj.age) // 前端小菜鸟, undefined 这里删除name属性没成功是因为name属性的configurable是false ,age属性删除成功所以是undefined
4、Object.defineProperty()方法:直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
语法:Object.defineProperty(obj, prop, descriptor) // obj: 目标对象; prop: 目标对象需要定义或修改的属性名; descriptor: 要定义或修改的属性描述符。
var obj = new Object();
Object.defineProperty(obj, 'name', {
configurable: false,
writable: true,
enumerable: true,
value: '前端小菜鸟'
})
console.log(obj.name) // 前端小菜鸟
console.log(Object.keys(obj)); // ['name]
obj.name = '老油条了'
console.log(obj.name) // 老油条了
delete obj.name
console.log(obj.name) // 老油条了
5、Object.getOwnPropertyDescriptor()方法:获取指定对象的属性描述符
话不多说 看示例
var obj = {name: '前端小菜鸟'}
var descriptor = Object.getOwnPropertyDescriptor(obj, "name");
console.log(descriptor);
/* 输出
{
value: '前端小菜鸟',
writable: true,
enumerable: true,
configurable: true
}
*/
var obj, descriptor;
obj = { get foo() { return 666; } };
descriptor = Object.getOwnPropertyDescriptor(obj, "foo");
console.log(obj.foo);
console.log(descriptor );
/* 输出
666
{
get: [Function: get foo],
set: undefined,
enumerable: true,
configurable: true
}
*/
6、Object.getOwnPropertyDescriptors()方法:获取一个对象的所有自身属性的描述符。
话不多说 看示例
var obj, descriptor;
obj = { name: '小菜鸟',age : 50 };
descriptor = Object.getOwnPropertyDescriptors(obj);
console.log(descriptor );
/* 输出
{
name: {
value: '小菜鸟',
writable: true,
enumerable: true,
configurable: true
},
age: { value: 50, writable: true, enumerable: true, configurable: true }
}
*/
7、Object.entries() 方法:返回一个目标对象自身可枚举属性的键值对组成的数组
语法: Object.entries(obj)
var obj = { name: '小菜鸟',age : 50 };
console.log(Object.entries(obj) ); // [ [ 'name', '小菜鸟' ], [ 'age', 50 ] ]
8、Object.fromEntries() 方法:把键值对数组转成一个对象
语法: Object.fromEntries(obj)
let arr = [ [ 'name', '小菜鸟' ], [ 'age', 50 ] ];
console.log(Object.fromEntries(arr)); // { name: '小菜鸟', age: 50 }
9、Object.freeze() 方法:冻结一个对象,被冻结的对象再也不能被修改(更改/删除已有属性,新增属性,更改属性修饰符等)
语法:Object.freeze(obj)
var obj = { name: '小菜鸟',age : 50 };
Object.freeze(obj); // 冻结obj
obj.name = '老油条了';
delete obj.age;
console.log(obj ); // obj不改变 { name: '小菜鸟', age: 50 }
10、Object.getOwnPropertyNames() 方法:返回目标对象所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
语法:Object.getOwnPropertyNames(obj)
var obj = Object.create({}, {
name: {
value: '小菜鸟',
enumerable: true
},
getName: {
value: function() { return this.name; },
enumerable: false
},
});
console.log(Object.getOwnPropertyNames(obj) ); // [ 'name', 'getName' ]
let attr = Symbol('老油条');
obj[attr] = 'test';
console.log(attr); // Symbol(老油条)
console.log(Object.getOwnPropertyNames(obj)); // [ 'name', 'getName' ] Symbol的属性名拿不到
console.log(obj); // { name: '小菜鸟', [Symbol(老油条)]: 'test' } 能打印出来呦
// 那如何拿Symbol的属性呢?
11、Object.getOwnPropertySymbols() 方法:返回目标对象自身的所有 Symbol 属性的数组。
说啥来啥么这不! 语法:Object.getOwnPropertySymbols(obj)
let obj = {},
attr = Symbol('老油条');
obj[attr] = '小菜鸟摸鱼进化终极形态';
console.log(Object.getOwnPropertySymbols(obj) ); // [ Symbol(老油条) ]
console.log(obj); // { [Symbol(老油条)]: '小菜鸟摸鱼进化终极形态' }
12、Object.getPrototypeOf() 方法:返回指定对象的原型(内部[[Prototype]]
属性的值)
语法:Object.getPrototypeOf(obj)
var proto = {};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true
// 该方法获取Object,Function请感兴趣的老油条们自行摸索一下
13、Object.hasOwn() 方法:返回布尔值,标识对象中是否存在该属性
语法:Object.hasOwn(obj, '属性名'),其实是Object.prototype.hasOwnProperty()方法的替代,语法不同作用一样,语法:Object.prototype.hasOwnProperty.call(obj,'属性名');
var obj = Object.create({}, {
name: {
value: '小菜鸟',
enumerable: true
},
getName: {
value: function() { return this.name; },
enumerable: false
},
});
console.log(Object.hasOwn(obj, 'name')); // true
console.log(obj.hasOwnProperty('name')); // true
console.log(Object.prototype.hasOwnProperty.call(obj,'name')); // true
14、Object.is() 方法:判断两个值是否为同一个值,返回布尔值
语法:Object.is(val1, val2);
console.log( Object.is(undefined, undefined)); // true
console.log( Object.is(null, null)); // true
console.log( Object.is(true, true)); // true
console.log( Object.is(false, false)); // true
console.log( Object.is('123', '123')); // true
console.log( Object.is(+0, +0)); // true
console.log( Object.is(-0, -0)); // true
console.log( Object.is(0, 0)); // true
console.log( Object.is(-0, 0)); // false 特殊呦
console.log( Object.is(+0, 0)); // true
console.log( Object.is(NaN, NaN)); // true
console.log( Object.is({name: '小菜鸟'}, {name: '小菜鸟'})); // false 引用地址不一样
let obj = {name: '老油条'};
console.log( Object.is(obj, obj)); // true
console.log( Object.is(window, window)); // true
console.log(Object.is(NaN, 0/0)); // true
15、Object.isExtensible() 方法:判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)布尔值
语法:Object.isExtensible(obj)
// 新建的对象默认都是可扩展的
var obj = {};
console.log(Object.isExtensible(obj)); // true
// 那怎么能变成不可扩展的呢?上面我们就学到了一个方法 那就是freeze方法
Object.freeze(obj);
console.log(Object.isExtensible(obj)); // false
// 和接下来学到的Object.preventExtensions()方法 以及Object.seal()方法
Object.preventExtensions(obj); // 使对象不可扩展
console.log(Object.isExtensible(obj)); // false
Object.seal(obj); // 使对象封闭
console.log(Object.isExtensible(obj)); // false
16、Object.preventExtensions() 方法:使对象不可扩展,也就是永远不能再添加新的属性,原有的属性可以修改和删除
语法:Object.preventExtensions(obj)
var obj = {
name: '小菜鸟'
};
console.log(Object.isExtensible(obj)); // true 可扩展
Object.preventExtensions(obj); // 变成不可扩展
console.log(Object.isExtensible(obj)); // false
obj.age = 50;
console.log(obj); // { name: '小菜鸟' } 无法新增属性
obj.name = '老油条';
console.log(obj); // { name: '老油条' } 可以更改属性值
delete obj.name;
console.log(obj); // {} 可以删除属性
17、Object.seal() 方法:封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。
语法:语法:Object.seal(obj)
var obj = {
name: '小菜鸟'
};
Object.seal(obj);
obj.age = 50;
console.log(obj); // { name: '小菜鸟' } 没法新增属性
obj.name = '老油条';
console.log(obj); // { name: '老油条' } 可更改原有属性 是因为新建对象的属性描述符默认是可配置的 所以可以修改
delete obj.name;
console.log(obj); // { name: '老油条' } 无法删除原有属性
18、Object.isSealed() 判断目标对象是否封闭,返回布尔值
语法:Object.isSealed(obj)
var obj = {};
console.log(Object.isSealed(obj)); // false 新建的对象默认不是封闭的
// 如果把一个空对象变的不可扩展,则它同时也会变成个密封对象.
Object.preventExtensions(obj); // 变为不可扩展的
console.log(Object.isSealed(obj)); // true
// 如果这个对象不是空对象,则它不会变成密封对象,因为密封对象的所有自身属性必须是不可配置的
let foo = {name: '小菜鸟'};
Object.preventExtensions(foo); // 变为不可扩展的
console.log(Object.isSealed(foo)); // false 因为源对象属性是可配置的
// 如果把这个属性变的不可配置,则这个属性也就成了密封对象.
Object.defineProperty(foo, 'name', {
configurable: false
});
console.log(Object.isSealed(foo)); // true
19、Object.isFrozen() 方法:判断对象是否被冻结,返回布尔值
语法:Object.isFrozen(obj)
// 一个对象默认是可扩展的,所以它也是非冻结的.
console.log(Object.isFrozen({})); // false
// 一个不可扩展的空对象同时也是一个冻结对象.
var foo = Object.preventExtensions({});
console.log(Object.isFrozen(foo)); // true;
// 一个非空对象默认也是非冻结的.
var obj = { name: '小菜鸟' };
console.log(Object.isFrozen(obj)); // false
// 让这个对象变的不可扩展,并不意味着这个对象变成了冻结对象,
// 因为p属性仍然是可以配置的(而且可写的).
Object.preventExtensions(obj);
console.log(Object.isFrozen(obj)); // false
// 此时,如果删除了这个属性,则它会成为一个冻结对象.
delete obj.name;
console.log(Object.isFrozen(obj)); // true
// 一个不可扩展的对象,拥有一个不可写但可配置的属性,则它仍然是非冻结的.
var bar = { name: '老油条' };
Object.preventExtensions(bar);
Object.defineProperty(bar, 'name', { writable: false }); // 变得不可写
console.log(Object.isFrozen(bar)); // false
// 把这个属性改为不可配置,会让这个对象成为冻结对象.
Object.defineProperty(bar, 'name', { configurable: false }); // 变得不可配置
console.log(Object.isFrozen(bar)); // true
// 使用Object.freeze是冻结一个对象最方便的方法.
var frozen = { feel: '头好大' };
console.log(Object.isFrozen(frozen)); // false
Object.freeze(frozen);
console.log(Object.isFrozen(frozen)); // true
// 一个冻结对象也是一个密封对象.
console.log(Object.isSealed(frozen)); // true
// 更是一个不可扩展的对象.
console.log(Object.isExtensible(frozen)); // false
整理到这里我的头已经俩个大了,建议感兴趣的同学反复观看
20、Object.keys() 方法:返回一个对象可枚举属性字符串组成的数组
语法:Object.keys(obj)
let obj = {
name: '小菜鸟',
age: 50
};
console.log(Object.keys(obj)); // [ 'name', 'age' ]
21、Object.values() 方法:返回一个对象可枚举属性值组成的数组
语法:Object.values(obj)
let obj = {
name: '小菜鸟',
age: 50
};
console.log(Object.values(obj)); // [ '小菜鸟', 50 ]
结语
整理起来真的挺不容易的 尤其是冻结,不可扩展,封闭这几个方法,绕来绕去的,头发蒙呀。如果这篇文章有帮助到你,就请点赞评论收藏下吧。