this 指向的迷之行为
javascript
const user = {
name: "John",
sayHi() {
console.log(this.name);
}
};
const sayHi = user.sayHi;
sayHi(); // 输出:undefined(严格模式下报错)
原因 :方法中的 this
取决于调用方式。当方法被单独调用时,this
指向全局对象(非严格模式)或 undefined
(严格模式)。
解决方案:
- 使用箭头函数(但箭头函数无自己的
this
) - 使用
bind
绑定上下文:const sayHi = user.sayHi.bind(user);
- 调用时指定上下文:
sayHi.call(user);
深拷贝与浅拷贝的误会
javascript
const obj = { a: 1, nested: { b: 2 } };
const shallowCopy = { ...obj };
shallowCopy.nested.b = 999;
console.log(obj.nested.b); // 输出:999(原对象被修改!)
原因 :展开运算符 ...
和 Object.assign()
只能实现浅拷贝,嵌套对象仍是引用。
解决方案:
- 使用
JSON.parse(JSON.stringify(obj))
(但无法处理函数、循环引用) - 使用 Lodash 的
_.cloneDeep()
- 手动递归实现深拷贝
属性遍历的隐藏属性
javascript
const obj = { a: 1 };
Object.defineProperty(obj, 'b', { value: 2, enumerable: false });
console.log(Object.keys(obj)); // 输出:["a"]
for (let key in obj) console.log(key); // 输出:"a"
console.log('b' in obj); // 输出:true
原因 :对象属性具有 enumerable
特性,默认值为 true
。通过 defineProperty
定义的属性若设为不可枚举,则无法被 for...in
或 Object.keys()
遍历,但仍可通过 in
运算符判断存在性。
解决方案:
- 使用
Object.getOwnPropertyNames()
获取所有自身属性(包括不可枚举) - 使用
Reflect.ownKeys()
获取所有键(包括 Symbol)
对象比较的错觉
javascript
console.log({} === {}); // false
console.log(NaN === NaN); // false
console.log(Object.is({}, {})); // false
console.log(Object.is(NaN, NaN)); // true
原因 :对象通过引用比较,即使内容相同,两个不同对象也不相等。而 NaN
在常规比较中不等于自身,但 Object.is()
能正确处理。
解决方案:
- 深比较:递归比较每个属性值
- 使用第三方库如 Lodash 的
_.isEqual()
ES6 的 Proxy 陷阱
javascript
const target = {};
const proxy = new Proxy(target, {
get(obj, prop) {
return prop in obj ? obj[prop] : 0;
}
});
proxy.a = 100;
console.log(proxy.a); // 100
console.log(proxy.b); // 0
console.log(target.b); // undefined(原对象未被修改)
原因:Proxy 可以拦截对象操作,但如果不显式操作目标对象,可能导致代理对象与原对象行为不一致。
解决方案:
- 始终通过代理对象操作
- 在处理器中正确处理反射方法
JSON 序列化的黑洞
javascript
const obj = {
date: new Date(),
fn: () => console.log("Hi"),
undefinedProp: undefined
};
const json = JSON.stringify(obj);
console.log(json); // 输出:{"date":"2023-10-01T12:00:00.000Z"}
原因 :JSON.stringify
会忽略 undefined
和函数,并将 Date
对象转为字符串。
解决方案:
- 自定义
toJSON
方法 - 使用
JSON.stringify
的replacer
参数处理特殊类型