目录
原型链:obj.__proto__===Obj.prototype
null:唯一不从 Object.prototype 继承的对象(防止原型污染攻击)
Object.prototype 的原型始终为 null 且不可更改
Function.prototype === Function.__proto__; // true
Function本身也是函数,所以 Function是Function的实例
Object静态方法/Object.prototype.方法.call(obj,...)
instanceof代替Obj.prototype.isPrototypeOf(obj)
Obj.get/setPrototypeOf(obj)代替obj._ _ proto _ _
Obj.hasOwn(obj, prop)代替Obj.prototype.hasOwnProperty()
Object.assign(target, ...sources)返回修改后的同地址的obj(target)
对象内容,而非地址Object.assign({}, obj)浅拷贝一层
Object.is(val0, val1):NaN等,±0不等
Obj.create(obj[,props]) 以实例作为原型,创建新对象
Object.defineProperties(obj,props)
enumerable:默认为 false,不可枚举(自有属性)
Object.prototype.propertyIsEnumerable(prop)
等价于 Object.getOwnPropertyDescriptor(obj, prop)?.enumerable ?? false
props+symbol:propertyDescripts
js判断数据类型、toString和valueOf区别,类型转换、不同类型间的运算、判断相等
作用:共享属性
原型:提供继承者共享属性/方法的对象
原型链:obj.__proto__===Obj.prototype
引用类型:
__proto__(隐式原型)
属性,属性值是对象
函数:
prototype(原型)
属性,属性值是对象
const o = {
a: 1,
b: 2,
// __proto__ 设置了 [[Prototype]]。它在这里被指定为另一个对象字面量。
__proto__: {
b: 3,
c: 4,
__proto__: {
d: 5,
},
},
};
// { a: 1, b: 2 } ---> { b: 3, c: 4 } ---> { d: 5 } ---> Object.prototype ---> null
console.log(o.d); // 5
null:唯一不从 Object.prototype
继承的对象(防止原型污染攻击)
const user = {};
// 恶意脚本:
Object.prototype.authenticated = true;
// 意外允许未经身份验证的用户通过
if (user.authenticated) {
// 访问机密数据
}
map 的简单替代品
const ages = { alice: 18, bob: 27 };
function hasPerson(name) {
return name in ages;
}
function getAge(name) {
return ages[name];
}
hasPerson("hasOwnProperty"); // true
getAge("toString"); // [Function: toString]
由于存在 Object.prototype
属性,会导致一些错误:
const ages = Object.create(null, {
alice: { value: 18, enumerable: true },
bob: { value: 27, enumerable: true },
});
hasPerson("hasOwnProperty"); // false
getAge("toString"); // undefined
Object.prototype
的原型始终为 null
且不可更改
Function.prototype === Function.__proto__; // true
Function本身也是函数,所以 Function是Function的实例
应用
函数装饰器:在一个函数 执行前 或 执行后 添加额外的逻辑
Function.prototype.before=function(beforefn){
return ()=>{
beforefn.apply(this,arguments)
return this.apply(this,arguments)
}
}
Function.prototype.after=function(afterfn){
return ()=>{
var res=this.apply(this,arguments)
afterfn.apply(this,arguments)
return res;
}
}
var func=function(){
console.log(1)
}.before(function(){
console.log(2)
}).after(function(){
console.log(3)
})
func()//213
Object
Object.prototype 方法:多态
应该避免调用任何 Object.prototype 方法,特别是那些不打算多态化的方法(即只有其初始行为是合理的,且无法被任何继承的对象以合理的方式重写),而尽量用Object的静态方法
Object静态方法/Object.prototype.方法.call(obj,...)
如果不存在语义上等价的静态方法,或者你真的想使用 Object.prototype
方法,你应该通过 call()直接在目标对象上调用 Object.prototype
方法,以防止因目标对象上原有方法被重写而产生意外的结果。
const obj = {
foo: 1,
// 如果可能的话,你不应该在自己的对象上定义这样的方法,
// 但是如果你从外部输入接收对象,可能无法防止这种情况的发生
propertyIsEnumerable() {
return false;
},
};
obj.propertyIsEnumerable("foo"); // false;预期外的结果
Object.prototype.propertyIsEnumerable.call(obj, "foo"); // true;预期的结果
instanceof代替Obj.prototype.isPrototypeOf(obj)
包含本身的类型,还有继承的父类型帕努单
Obj.get/setPrototypeOf(obj)代替obj._ _ proto _ _
Obj.hasOwn(obj, prop)代替Obj.prototype.hasOwnProperty()
在支持 Object.hasOwn 的浏览器中,建议使用 Object.hasOwn(),而非
hasOwnProperty()
。1.与重写的hasOwnProperty一起使用
const foo = { hasOwnProperty() { return false; }, bar: "The dragons be out of office", }; if (Object.hasOwn(foo, "bar")) { console.log(foo.bar); //true——重新实现 hasOwnProperty() 不会影响 Object }
2.测试使用 Object.create(null) 创建的对象。这些对象不会继承自
Object.prototype
,因此hasOwnProperty()
方法是无法访问的。const foo = Object.create(null); foo.prop = "exists"; if (Object.hasOwn(foo, "prop")) { console.log(foo.prop); //true——无论对象是如何创建的,它都可以运行。 }
Object.assign(target, ...sources)返回修改后的同地址的obj(target)
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
// Expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget === target);
// Expected output: true
对象内容,而非地址Object.assign({}, obj)浅拷贝一层
let obj1 = { key: 'value' };
let obj2 = Object.assign({}, obj1); // 创建obj1的浅拷贝
obj1.key = 'new value';
console.log(obj2.key); // 输出: 'value'
Object.is(val0, val1):NaN等,±0不等
严格值相等
===、==:NaN不等、±0等
Obj.create(obj[,props]
) 以实例作为原型,创建新对象
props等价于Object.defineProperties的props
Object.defineProperties(obj,props)
const object1 = {};
Object.defineProperties(object1, {
property1: {
value: 42,
writable: true,
},
property2: {},
});
console.log(object1.property1);
// Expected output: 42
数据描述符
configurable:默认false,不可删改
enumerable:默认为 false,
不可枚举(自有属性)
大多数内置属性默认情况下是不可枚举的
Object.prototype.propertyIsEnumerable(prop)
等价于 Object.getOwnPropertyDescriptor(obj, prop)?.enumerable ?? false
??
是空值合并操作符(Nullish Coalescing Operator)
value: 默认 undefined
writable:默认false,不能用赋值运算符修改
访问器描述符
get:默认undefined,函数返回值将被用作属性的值
set:默认undefined
arr:Object.keys()/values()
运算符
delete obj.property
delete obj[property]
试图删除的属性不存在,那么 delete
将不会起任何作用,但仍会返回 true
property in
obj
const trees = ["redwood", "bay", "cedar", "oak", "maple"];
trees[3] = undefined;
console.log(3 in trees); // true
自身和继承
all:in操作符
可枚举:for in
自身可枚举:Object.keys
props:propertyNames
props+symbol:propertyDescripts
Object.getOwnPropertyDescriptor(obj, prop)