万物皆对象之对象方法大全

309 阅读9分钟

前言

在JavaScript中,几乎所有的对象都是Object类型的实例,它们都会从Object.prototype继承属性和方法。这篇文章来总结下对象都有哪些方法。

obj.png

从上图我们可以看到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 ]

结语

整理起来真的挺不容易的 尤其是冻结,不可扩展,封闭这几个方法,绕来绕去的,头发蒙呀。如果这篇文章有帮助到你,就请点赞评论收藏下吧。