Object.defineProperty(obj, key, descriptor)
在一个对象上定义或修改一个属性
返回修改后的对象
属性:
- obj 要修改或定义属性的对象
- key 要修改或定义的属性的名称
- descriptor 要定义或修改的属性的描述符
下面在 obj 上定义一个不可赋值的属性 “name”:
const obj = {};
Object.defineProperty(obj, 'name', {
writable: false,
value: 'link'
})
obj.name = 'ok'; // 由于 obj.name 不可写入,所以该赋值无效
console.log(obj.name); // link
Object.create(proto, properties)
创建一个新对象
第一个参数会被作为新对象的原型
第二个参数是想要添加在新对象自身的属性,是可枚举的
let _proto = {
sayHello(){
console.log('Hello ', this.name)
}
}
let o = Object.create(_proto, {
'name': {
writable: true,
configurable: true,
value: "link",
}
})
o.sayHello(); // Hello link
可以用来创建一个纯净的对象,下面创建出来的对象是没有 toString 方法的
let o = Object.create(null)
o.toSrting; // undefined
Object.getOwnPropertyDescriptor(obj, 'key');
获取对象属性的描述
- obj 目标对象
- key 要获取描述的对象的属性
上面的代码中显示了 obj.name 的属性
- enumerable 可枚举性
- true 可枚举
- false 不可枚举
如果属性设置了不可枚举,那么以下操作将会忽略该属性:
- for...in 循环遍历可枚举属性
- Object.key() 返回对象可枚举属性的值
- JSON.stringify() 将对象转换为字符串对象,如果有不可枚举的属性会被忽略
- Object.assign() 浅拷贝对象,忽略不可枚举的对象
如下: obj 对象原型上的 toString 就是不可枚举的,所以我们使用 for...in 是不能遍历到它的。
ES6 规定,所有的 Class 原型方法都是不可枚举的
属性的遍历
- for...in
- 遍历对象自身和继承来的可枚举的属性,不包含 Symbol 属性
- Object.keys(obj)
- 返回一个包含对象自身的可枚举的键的数组
- Object.getOwnPropertyNames(obj)
- 返回一个包含对象自身的键,包括不可枚举的键的数组,但不包括 Symbol 属性
- object.getOwnPropertySysbols(obj)
- 返回一个包含对象自身所有的 Symbol 属性的数组
- Reflect.ownKeys(obj)
-
返回一个包含对象自身所有属性的键名的数据,不管是否可枚举或是否是 Symbol 属性。
-
super 关键字
this 关键字总是指向函数所在的当前对象。
super 关键字指向当前对象的原型对象
super 关键字表示原型对象时,只能写在对象的方法之中。
super 关键字表示原型对象时,只能写在对象的方法之中。 以下下都是错误写法:
// 报错,不能写在属性之中
const obj = {
foo: super.foo
}
// 报错
// 这个为什么报错呢,因为他是写在函数当中,然后再把这个函数赋值 foo
const obj = {
foo: function(){
return super.foo
}
}
下面是正确写法
- 目前只有对象方法的简写可以让 JavaScript 引擎确认定义的是对象方法。
const obj = {
foo: 'world',
find() {
console.log(super.foo);
}
};
obj.__proto__.foo = "Hello World";
obj.find(); // Hello World
链判断运算符(ES2020)
直接在链式的时候判断左侧的对象是否为 null 或 undefined,如果是,直接返回 undefined,不在继续往下走。
如下:常见做法就是一层一层的 &&。
const name = (
message
&& message.body
&& message.body.user
&& message.body.user.name) || undefined;
)
ES2020写法
const name = message?.body?.user?.name || undefined;
Object.is()
用来比较两个值是否严格相等
与严格比较符行为基本相等,但是有两个不同之处
1、Object.is(-0, 0) // false
+0 === -0 // true
2、Object.is(NaN, NaN) // true
NaN === NaN // false
Object.is('foo', 'foo'); // true
Object.is({}, {}); // false
Object.assign()
用于合并对象,将源对象(用来合并的对象)的所有可枚举属性复制到目标对象
是浅拷贝
如果参数不是对象,会先转换为对象
let a = {name: 'link'}
let b = {age: 17}
let c = {gender: 'boy'}
Object.assign(a, b, c)
console.log(a) // { name: 'link', age: 17, gender: 'boy' }
如果参数不是对象,自动转换为对象再合并
let a = Object.assign({}, 'hello')
console.log(a); // { '0': 'h', '1': 'e', '2': 'l', '3': 'l', '4': 'o' }
如果被合并的源是其他类型的值,那么只有字符串会被转换为数组形式合并进来,其他的会被忽略
let a = Object.assign({}, 1,2,true, 'hello')
console.log(a);
// { '0': 'h', '1': 'e', '2': 'l', '3': 'l', '4': 'o' }
同名属性会被后面合并进来的替换
let a = {
name: 'ok'
}
let b = {
name: 'link'
}
Object.assign(a, b)
console.log(a);
// { name: 'link' }
如果参数都是数组
如果参数都是数组,会把数组中元素的下标当做键,然后合并
let a = [1, 2, 3];
let b = [4, 5];
Object.assign(a, b)
console.log(a);
// [ 4, 5, 3 ]
Object.getOwnPropertyDescriptors() 【ES2017】
返回某个对象的所有自身属性的描述对象
与 Object.getOwnPropertyDescript() 的区别是:
Object.getOwnPropertyDescriptor() 只能获取对象自身的某个属性的描述
Object.getOwnPropertyDescriptors() 是获取对象自身的所有属性的描述
{
name: {
value: 'link',
writable: true,
enumerable: true,
configurable: true
},
bar: {
get: [Function: get bar],
set: undefined,
enumerable: true,
configurable: true
}
}
可以用来解决 Object.assign() 无法合并 get 和 set 属性
const a = {
set foo(v){
console.log(v);
}
}
const t = Object.assign({}, a)
console.log(t); // { foo: undefined }
使用 Object.getOwnPropertyDescriptots() 配合 Object.defineProperties() 来解决这个问题
const a = {
set foo(v){
console.log(v);
}
}
const t = Object.defineProperties({}, Object.getOwnPropertyDescriptors(a))
console.log(t); // { foo: [Setter] }
__ proto __ 属性
该属性没有写入 ES6 正文,只写入到附录中,标准明确规定浏览器必须部署这个属性,
而其他环境就可以不部署,所以我们尽量忽略这个属性
__ proto __ 使实例能够访问到 prototype
function Parent (){}
const p = new Parent()
console.log(p.__proto__ === Parent.prototype)
Object.setPrototypeOf(object, prototype)
Object.setPrototypeOf() 用来设置对象的原型对象,返回参数本身
Object.setPrototypeOf(object, prototype)
// 等价于
function(object, prototype){
object.__proto__ = prototype;
return object;
}
Object.getPrototypeOf(obj)
Object.getPrototypeOf() 用于获取对象的原型
function Parent(){}
const p = new Parent()
Object.getPrototypeOf(p) === Parent.prototype; // true
Object.keys()
返回一个包含对象自身的可枚举属性的数组
var obj = { foo: 'bar', baz: 'bar' };
Object.keys(obj)
// ["foo", "baz"]
Object.values()
返回一个包含对象自身的可枚举值的数组
var obj = { foo: 'bar', baz: 'opq' };
Object.values(obj)
// ["bar", "opq"]
Object.entries()
返回一个数组,元素是对象的的键值对数组
var parent = {
name: 'link',
age: 12
}
Object.entries(parent) // [ [ 'name', 'link' ], [ 'age', 12 ] ]
Object.fromEntries()
Object.entries 的方向操作,将一个键值对数组转换为对象
Object.fromEntries([ ['foo', 'bar'],
['baz', 42]
])
// { foo: "bar", baz: 42 }