面试官:ES6中对象新增了哪些扩展?

文摘   2024-11-16 10:07   山西  

作为一个前端开发工程师,面试中经常会碰到对象的新特性这个问题。面试官们一问“对象新增了哪些扩展?”这还真是能把不少人难倒。

其实呢,ES6以来,JavaScript对象确实新增了很多特性,既提升了代码的可读性,也让开发过程更加便捷。下面我就来详细梳理一下这些新特性,外加一些代码例子,大家可以随手复制粘贴到控制台里运行一下,看看效果。

首先,我们来说说属性的简写。在ES6中,当对象的键名和对应的变量名一样时,可以直接省略赋值。以前我们可能会这样写:

const foo = 'bar';
const baz = { foo: foo };

但在ES6中,这可以简写成:

const foo = 'bar';
const baz = { foo };

不仅是属性,方法也可以简写。如果我们有一个对象需要定义方法,以前的写法是这样:

const o = {
  methodfunction({
    return "Hello!";
  }
};

在ES6中,可以这样写:

const o = {
  method() {
    return "Hello!";
  }
};

简洁很多吧?不过这里要注意一点,简写的对象方法不能用作构造函数,否则会报错。试试下面的代码:

const obj = {
  f() {
    this.foo = 'bar';
  }
};

new obj.f(); // 报错

再来说一个有意思的功能属性名表达式。在ES6之前,对象的属性名是固定的字符串,动态生成非常麻烦。但ES6允许在对象定义中直接使用表达式作为属性名。比如:

let lastWord = 'last word';
const a = {
  'first word''hello',
  [lastWord]: 'world'
};

console.log(a['first word']); // "hello"
console.log(a[lastWord]);      // "world"
console.log(a['last word']);   // "world"

这样我们就可以灵活定义属性名。另外,方法名同样可以是表达式。比如:

let obj = {
  ['h' + 'ello']() {
    return 'hi';
  }
};

console.log(obj.hello()); // "hi"

不过要注意,如果尝试同时使用属性名表达式和简洁表示法会报错。正确用法如下:

const foo = 'bar';
const baz = { [foo]: 'abc' }; // 正确

接下来是super关键字。这个关键字之前只在类中见过,现在也可以用于对象字面量,指向对象的原型。来看一个例子:

const proto = { foo'hello' };

const obj = {
  foo'world',
  find() {
    return super.foo;
  }
};

Object.setPrototypeOf(obj, proto);
console.log(obj.find()); // "hello"

这个代码段中的super指向proto对象。这样,obj.find()返回的就是protofoo属性。

扩展运算符在对象中也是一项极大的提升。扩展运算符...可以用来解构赋值,提取对象中的剩余属性,非常实用。举个例子:

let { x, y, ...z } = { x1y2a3b4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }

注意一点,扩展运算符用在解构赋值时必须是最后一个参数,否则会报错。另外,扩展运算符是浅拷贝。如果有嵌套对象,修改原对象中的嵌套属性,解构出来的新对象也会受到影响。

再来看看对象的遍历方法。ES6中有五种常用的属性遍历方式:

  1. for...in:遍历对象的可枚举属性(包括继承属性)。
  2. Object.keys(obj):返回对象自身的可枚举属性键名(不包括继承属性)。
  3. Object.getOwnPropertyNames(obj):返回对象自身的所有属性(包括不可枚举属性)。
  4. Object.getOwnPropertySymbols(obj):返回对象自身的所有Symbol属性。
  5. Reflect.ownKeys(obj):返回对象自身的所有键名(包括不可枚举和Symbol)。

看个例子:

console.log(Reflect.ownKeys({ [Symbol()]:0b:010:02:0a:0 }));
// 输出顺序是 ['2', '10', 'b', 'a', Symbol()]

这个顺序规则是:数值键按升序,字符串键按添加顺序,Symbol键按添加顺序。

最后,我们来说说ES6新增的对象方法:

Object.is()

严格判断两个值是否相等,特别之处是+0不等于-0,但NaN等于NaN

console.log(Object.is(+0-0)); // false
console.log(Object.is(NaNNaN)); // true

Object.assign()

用于对象的合并,将源对象的属性复制到目标对象。遇到同名属性会替换。注意,Object.assign()是浅拷贝:

const target = { a1b1 };
const source = { b2c3 };
Object.assign(target, source);
console.log(target); // { a: 1, b: 2, c: 3 }

Object.getOwnPropertyDescriptors()

获取对象的所有属性描述信息。这个方法常用在深拷贝等场景:

const obj = {
  foo123,
  get bar() { return 'abc'; }
};

console.log(Object.getOwnPropertyDescriptors(obj));

Object.setPrototypeOf() 和 Object.getPrototypeOf()

Object.setPrototypeOf用来设置对象的原型,Object.getPrototypeOf用来读取对象的原型:

const o = Object.setPrototypeOf({}, null);
console.log(Object.getPrototypeOf(o)); // null

Object.keys()、Object.values()、Object.entries()

这些方法分别用于获取对象的键名、键值和键值对数组:

const obj = { foo'bar'baz42 };
console.log(Object.keys(obj)); // ["foo", "baz"]
console.log(Object.values(obj)); // ["bar", 42]
console.log(Object.entries(obj)); // [["foo", "bar"], ["baz", 42]]

Object.fromEntries()

用于将键值对数组转为对象。这个方法通常和Object.entries()搭配使用,特别在Map对象的处理上非常方便:

const entries = [['foo''bar'], ['baz'42]];
console.log(Object.fromEntries(entries)); // { foo: "bar", baz: 42 }

综上所述,如果面试官问起“对象新增了哪些扩展?”可以这样回答:

ES6引入了一系列新特性来增强对象的功能,比如属性和方法的简写、属性名表达式、super关键字、扩展运算符等。另外,还增加了许多遍历对象属性的新方法,比如Object.keys、Object.values和Object.entries。同时,像Object.assign、Object.is、Object.getOwnPropertyDescriptors、Object.setPrototypeOf和Object.fromEntries这些方法也让对象的操作更加灵活高效。

目前,对编程、职场感兴趣的同学,大家可以联系我微信:golang404,拉你进入“程序员交流群”。

虎哥私藏精品 热门推荐

虎哥作为一名老码农,整理了全网最前端资料合集

资料包含了《前端面试题PDF合集》、《前端学习视频》、《前端项目及源码》,总量高达108GB。

全部免费领取全面满足各个阶段程序员的学习需求!

web前端专栏
回复 javascript,获取前端面试题。分享前端教程,AI编程,AI工具,Tailwind CSS,Tailwind组件,javascript教程,webstorm教程,html教程,css教程,nodejs教程,vue教程。
 最新文章