前端面试基础 - Object的常用方法总结

164 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

得不得奖的无所谓希望能强迫自己闯一关╮( ̄▽ ̄)╭,上次更文未通关,这次继续

前言

记录常用 Object 方法的学习总结,梳理一些笔者可能比较容易忘的数组的api
有误请多多指正,附上女神图保命 [手动狗头]
学习已完成

  • 1.Object.create/assign 与 ES6扩展运算符(...) - 对象创建与合并
  • 2.Object.is - 判断两个值是否为同一个值
  • 3.Object.entries/fromEntries/keys/values - 键值对
  • 4.Object.prototype.constructor/isPrototypeOf/hasOwnProperty() - 构造函数/判断一个对象是否存在与另一个的原型链上/只判断对象自身不包含原型链
  • 5.Object.getPrototypeOf/setPrototypeOf - 回指定对象的原型/设置一个指定的对象的原型
  • 6.Object.seal/freeze/preventExtensions - 封闭/冻结/不可扩展 对象

1.Object.create/assign

Object.create

Object.create()  方法创建一个新对象,使用现有的对象来提供新创建的对象的 proto。(请打开浏览器控制台以查看运行结果。)

const its = Object.create(null); // 创建一个空对象

image.png

基于已有的对象A创建一个对象B, 创建后的B对象原型指向A,即 B.__proto__ === AObject.getPrototypeOf(me) === person

const person = {
  isHuman: false,
  printIntroduction: function() {
    console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
  }
};

const me = Object.create(person);

me.name = 'Matthew'; // "name" is a property set on "me", but not on "person"
me.isHuman = true; // inherited properties can be overwritten

me.printIntroduction();
// expected output: "My name is Matthew. Am I human? true"

语法如下

Object.create(proto,[propertiesObject])
  • proto 新创建对象的原型对象。
  • propertiesObject 可选。需要传入一个对象,该对象的属性类型参照[Object.defineProperties()]的第二个参数。且[不可枚举,参考下面 Object.keys] 返回值是一个新对象,带着指定的原型对象和属性。

Object.assign

Object.assign 方法只会拷贝源对象 可枚举的 和 自身的 属性到目标对象。

如下 target 对象会被改变,而源对象 source 会保持原来的值,被拷贝过来 target 的值,会覆盖 target 同名属性值

const target = { a: 1, b: 4 };
const source = { b: 3, c: 7 };

const returnedTarget = Object.assign(target, source);
console.log(target);
// expected output: Object { a: 1, b: 3, c: 7 }
console.log(source);
// expected output: Object { b: 3, c: 7 }
console.log(returnedTarget);
// expected output: Object { a: 1, b: 3, c: 7 }

const returnedTarget2 = {...target, ...source} // 使用ES6扩展运算符则target和source都不会改变 通常用于 复制对象

const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }

针对 深拷贝 需要使用其他办法,参考这篇文章的实现JS实现深克隆,因为 Object.assign() 只复制属性值。

2.Object.is 判断两个值是否为同一个值

必须同时满足以下值才相等

  • 都是 [undefined]
  • 都是 [null]
  • 都是 true 或都是 false
  • 都是相同长度、相同字符、按相同顺序排列的字符串
  • 都是相同对象(意味着都是同一个对象的值引用)
var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo); // true
Object.is(foo, bar); // false
Object.is({}, {}); // false
Object.is([], []); // false
  • 都是数字且
    • 都是 +0
    • 都是 -0
    • 都是 NaN
    • 都是同一个值,非零且都不是 NaN Object.is() 与 ==不同,Object.is 不会强制转换两边的值

Object.is() 与 ===不同,对待有符号的零和 NaN 不同, 例如,=== 运算符(也包括 == 运算符)将数字 -0 和 +0 视为相等,而将 [Number.NaN] 与 [NaN] 视为不相等。

3.Object.entries/keys/values

Object.entries

Object.entries() 方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 [for...in] 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。

const object1 = {
  a: 'somestring',
  b: 42
};
object1.__proto__.c = 222
console.log('----entries------')
for (const [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`);
}

console.log('----for in------')
for (let key in object1) {
  console.log(`${key}: ${object1[key]}`);
}

// expected output:
// ----entries------
// a: somestring
// b: 42
// ----for in------
// a: somestring
// b: 42
// c: 222

image.png

Object.fromEntries

方法 Object.fromEntries() 把键值对列表转换为一个对象,这个方法是和 Object.entries() 相对的。

const obj = {
    name: 'jimmy',
    age: 18
}
const entries = Object.entries(obj)
console.log(entries)
// [Array(2), Array(2)]

const fromEntries = Object.fromEntries(entries)
console.log(fromEntries)
// {name: "jimmy", age: 18}

Object.keys

Object.keys()  方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致。

// simple array
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']

// array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']

// array like object with random key ordering
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']
console.log(Object.keys('foo')); // ['0', '1', '2']

Object.create 创建的第二个参数 是不可枚举的,所以 getFoo 不会打印

// getFoo is a property which isn't enumerable
var myObj = Object.create({}, {
  getFoo: {
    value: function () { return this.foo; }
  }
});
myObj.foo = 1;
console.log(Object.keys(myObj)); // console: ['foo']

Object.values

Object.values() 方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用[for...in]循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。

特点与 Object.keys 是差不多的,只是访问的是 value

var obj = { foo: 'bar', baz: 42 };
console.log(Object.values(obj)); // ['bar', 42]

// array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj)); // ['a', 'b', 'c']

// array like object with random key ordering
// when we use numeric keys, the value returned in a numerical order according to the keys
var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(an_obj)); // ['b', 'c', 'a']

// non-object argument will be coerced to an object
console.log(Object.values('foo')); // ['f', 'o', 'o']

Object.create 创建的第二个参数 是不可枚举的,所以 getFoo 不会打印

var my_obj = Object.create({}, { getFoo: { value: function() { return this.foo; } } });
my_obj.foo = 'bar';
console.log(Object.values(my_obj)); // ['bar']

4.Object.prototype.constructor/isPrototypeOf/hasOwnProperty()

constructor 属性返回 [Object]的构造函数(用于创建实例对象)。注意,此属性的值是对函数本身的引用,而不是一个包含函数名称的字符串。

所有对象(使用 Object.create(null) 创建的对象除外)都将具有 constructor 属性。在没有显式使用构造函数的情况下,创建的对象(例如对象和数组文本)将具有 constructor 属性,这个属性指向该对象的基本对象构造函数类型。

const o = {}
o.constructor === Object // true
const o = new Object()
o.constructor === Object // true
const a = []
a.constructor === Array // true
const a = new Array()
a.constructor === Array // true
const n = new Number(3)
n.constructor === Number // true

isPrototypeOf()  方法用于测试一个对象是否存在于另一个对象的原型链上。isPrototypeOf

hasOwnProperty()  方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。不会访问原型链上的属性 hasOwnProperty

5.Object.getPrototypeOf/setPrototypeOf

getPrototypeOf

const prototype1 = {};
const object1 = Object.create(prototype1);

// 以下两个是等价的
console.log(Object.getPrototypeOf(object1) === prototype1); // true
console.log(object1.__proto__ === prototype1); // true

setPrototypeOf

Object.setPrototypeOf(obj, prototype)
  • obj 要设置其原型的对象。
  • prototype 该对象的新原型 (一个对象 或 [null]
  • Object.setPrototypeOf() 是给对象设置原型,是为了让大量 obj.__proto__ = .... 这种写法更优雅,有更好的兼容性。
const prototype1 = {a:1};
const object1 = Object.setPrototypeOf({}, prototype1)

image.png

6.Object.seal/freeze/preventExtensions

Object.seal

Object.seal() 方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。

Object.freeze

Object.freeze()  方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改freeze() 返回和传入的参数相同的对象。

Object.preventExtensions

Object.preventExtensions() 方法让一个对象变的不可扩展,也就是永远不能再添加新的属性

最后

以上的方式总结只是自己学习总结,有其他方式欢迎各位大佬评论
渣渣一个,欢迎各路大神多多指正,不求赞,只求监督指正( ̄. ̄)
有关文章经常被面试问到可以帮忙留下言,小弟也能补充完善完善一起交流学习,感谢各位大佬(~ ̄▽ ̄)~