原型、原型链、判断数据类型、Object方法和运算符

目录

作用:共享属性

原型链:obj.__proto__===Obj.prototype

引用类型:__proto__(隐式原型)属性,属性值是对象

函数:prototype(原型)属性,属性值是对象

 null:唯一不从 Object.prototype 继承的对象(防止原型污染攻击)

 map 的简单替代品

Object.prototype 的原型始终为 null 且不可更改

Function.prototype === Function.__proto__; // true

Function本身也是函数,所以 Function是Function的实例

应用

函数装饰器:在一个函数 执行前 或 执行后 添加额外的逻辑

Object

Object.prototype 方法:多态

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不等

===、==:NaN不等、±0等

Obj.create(obj[,props]) 以实例作为原型,创建新对象

Object.defineProperties(obj,props)

数据描述符

configurable:默认false,不可删改

enumerable:默认为 false,​不可枚举(自有属性​)

Object.prototype.propertyIsEnumerable(prop)

等价于 Object.getOwnPropertyDescriptor(obj, prop)?.enumerable ?? false

value: 默认 undefined

writable:默认false,不能用赋值运算符修改

访问器描述符

get:默认undefined,函数返回值将被用作属性的值

set:默认undefined

arr:Object.keys()/values()

运算符

delete obj.property

delete obj[property]

property in obj

自身和继承

all:in操作符

可枚举:for in

自身可枚举:Object.keys

props:propertyNames

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)

左侧为 null 或者 undefined 时,返回其右侧,否则返回左侧

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)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值