1、函数参数的默认值
ES6 允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}
// 等同于
const baz = {foo: foo};
let birth = '2000/01/01';
const Person = {
name: '张三',
//等同于birth: birth
birth,
// 等同于hello: function ()...
hello() { console.log('我的名字是', this.name); }
};
2、属性名表达式
在高程中已经分享过,一起回顾
// 方法一
obj.foo = true;
// 方法二
obj['a' + 'bc'] = 123;
let propKey = 'foo';
let obj = {
[propKey]: true,
['a' + 'bc']: 123
};
let lastWord = 'last word';
const a = {
'first word': 'hello',
[lastWord]: 'world'
};
a['first word'] // "hello"
a[lastWord] // "world"
a['last word'] // "world"
let obj = {
['h' + 'ello']() {
return 'hi';
}
};
obj.hello() // hi
错误用法
const keyA = {a: 1};
const keyB = {b: 2};
const myObject = {
[keyA]: 'valueA',
[keyB]: 'valueB'
};
myObject // Object {[object Object]: "valueB"}
3、方法的 name 属性
函数的name属性,返回函数名。对象方法也是函数,因此也有name属性。
const person = {
sayName() {
console.log('hello!');
},
};
person.sayName.name // "sayName"
其它 篇幅自己看
4、Object.is()
参考我分享的ES5基础
5、Object.assign()
完全按照阮一峰es6讲,写的非常全面
基本用法
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)
5.1) 源对象(source)可以有无限多个,目标对象(target)只能有一个
5.2) undefined和null无法转成对象,所以如果它们作为参数,就会报错
Object.assign(undefined) // 报错
Object.assign(null) // 报错
5.3) 如果该参数不是对象,则会先转成对象,然后返回。
console.log(typeof Object.assign(2));
console.log(Object('abc'))
console.log(Object(10))
console.log(Object(true))
const abc = Object.assign(2, {ID:1},{name:3});
console.log(abc)
5.4) Object.assign拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)。
5.5) Object.assign替换方法 ...运算符
{...obj}
{...obj,...obj2}
注意点
1) 浅拷贝
Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
2) 同名属性的替换
对于这种嵌套的对象,一旦遇到同名属性,Object.assign的处理方法是替换,而不是添加。
const target = { a: { b: 'c', d: 'e' } }
const source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }
3) 数组的处理
Object.assign可以用来处理数组,但是会把数组视为对象。
Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]
4) 取值函数的处理
Object.assign只能进行值的复制,如果要复制的值是一个取值函数,那么将求值后再复制。
const source = {
get foo() { return 1 },
get fhh() { return 2 }
};
const target = {};
console.log(Object.assign(target, source));
console.log(source);
上面代码中,source对象的foo属性是一个取值函数,Object.assign不会复制这个取值函数,只会拿到值以后,将这个值复制过去。
常见用途
1)为对象添加属性
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}
// 看输出效果
const point = new Point();
console.log(point);
上面方法通过Object.assign方法,将x属性和y属性添加到Point类的对象实例
2)为对象添加方法
Object.assign(SomeClass.prototype, {
someMethod(arg1, arg2) {
···
},
anotherMethod() {
···
}
});
// 等同于下面的写法
SomeClass.prototype.someMethod = function (arg1, arg2) {
···
};
SomeClass.prototype.anotherMethod = function () {
···
};
上面代码使用了对象属性的简洁表示法,直接将两个函数放在大括号中,再使用assign方法添加到SomeClass.prototype之中。
3)克隆对象
function clone(origin) {
return Object.assign({}, origin);
}
上面代码将原始对象拷贝到一个空对象,就得到了原始对象的克隆。
不过,采用这种方法克隆,只能克隆原始对象自身的值,不能克隆它继承的值。如果想要保持继承链,可以采用下面的代码。
function clone(origin) {
let originProto = Object.getPrototypeOf(origin);
return Object.assign(Object.create(originProto), origin);
}
4)合并多个对象
const merge =
(target, ...sources) => Object.assign(target, ...sources);
如果希望合并后返回一个新对象,可以改写上面函数,对一个空对象合并。
const merge =
(...sources) => Object.assign({}, ...sources);
推荐
{...sources}
5)为属性指定默认值
自己看
可枚举性
let obj = { foo: 123 };
console.log(Object.getOwnPropertyDescriptor(obj, 'foo'));
实例
var o = {a:1, b:2};
o.c = 3;
Object.defineProperty(o, 'd', {
value: 4,
enumerable: false
});
o.d
// 4
for( var key in o ) console.log( o[key] );
// 1
// 2
// 3
console.log(Object.keys(o));// ["a", "b", "c"]
console.log(JSON.stringify(o)); // => "{a:1,b:2,c:3}"
有四个操作会忽略enumerable为false的属性。
for...in循环:只遍历对象自身的和继承的可枚举的属性。
Object.keys():返回对象自身的所有可枚举的属性的键名。
JSON.stringify():只串行化对象自身的可枚举的属性。
Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。
属性的遍历
ES6 一共有 5 种方法可以遍历对象的属性。
(1)for...in
for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。
(2)Object.keys(obj)
Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
以上的 5 种方法遍历对象的键名,都遵守同样的属性遍历的次序规则。
首先遍历所有数值键,按照数值升序排列。
其次遍历所有字符串键,按照加入时间升序排列。
最后遍历所有 Symbol 键,按照加入时间升序排列。
Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
// ['2', '10', 'b', 'a', Symbol()]
上面代码中,Reflect.ownKeys方法返回一个数组,包含了参数对象的所有属性。这个数组的属性次序是这样的,首先是数值属性2和10,其次是字符串属性b和a,最后是 Symbol 属性。
尽量不要用for...in循环,而用Object.keys()代替
6、Object.keys(),Object.values(),Object.entries()
var obj = { foo: 'bar', baz: 42 };
console.log(Object.keys(obj)) //[ 'foo', 'baz' ]
console.log(Object.values(obj)) //[ 'bar', 42 ]
console.log(Object.entries(obj)) //[ [ 'foo', 'bar' ], [ 'baz', 42 ] ]
ES2017 [引入] 了跟Object.keys
配套的Object.values
和Object.entries
,作为遍历一个对象的补充手段,供for...of
循环使用
let {keys, values, entries} = Object;
let obj = { a: 1, b: 2, c: 3 };
for (let key of keys(obj)) {
console.log(key); // 'a', 'b', 'c'
}
for (let value of values(obj)) {
console.log(value); // 1, 2, 3
}
for (let [key, value] of entries(obj)) {
console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
}
let obj = { one: 1, two: 2 };
for (let [k, v] of Object.entries(obj)) {
console.log(
`${JSON.stringify(k)}: ${JSON.stringify(v)}`
);
}
实战
var data = {a:1, b:2};
const arr = [];
Object.entries(data).forEach(([key, value]) => {
if (typeof value !== 'undefined' && value != null) {
arr.push(key + '=' + encodeURIComponent(value));
}
});
console.log(arr.join('&'));
// 为什么是这个样子,[key, value]
console.log(Object.entries(data));
//注意key,value的解构赋值
7、Object.getOwnPropertyDescriptor
Object.getOwnPropertyDescriptor方法会返回某个对象属性的描述对象(descriptor)。ES2017 引入了Object.getOwnPropertyDescriptors方法,返回指定对象所有自身属性(非继承属性)的描述对象。
const obj = {
foo: 123,
get bar() { return 'abc' }
};
Object.getOwnPropertyDescriptors(obj)
// { foo:
// { value: 123,
// writable: true,
// enumerable: true,
// configurable: true },
// bar:
// { get: [Function: get bar],
// set: undefined,
// enumerable: true,
// configurable: true } }
解决Object.assign()无法正确拷贝get属性和set属性的问题
const source = {
set foo(value) {
console.log(value);
}
};
const target1 = {};
Object.assign(target1, source);
Object.getOwnPropertyDescriptor(target1, 'foo')
// { value: undefined,
// writable: true,
// enumerable: true,
// configurable: true }
Object.getOwnPropertyDescriptors方法配合Object.defineProperties方法,就可以实现正确拷贝。
const source = {
set foo(value) {
console.log(value);
}
};
const target2 = {};
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
Object.getOwnPropertyDescriptor(target2, 'foo')
// { get: undefined,
// set: [Function: set foo],
// enumerable: true,
// configurable: true }
上面代码中,两个对象合并的逻辑可以写成一个函数。
const shallowMerge = (target, source) => Object.defineProperties(
target,
Object.getOwnPropertyDescriptors(source)
);
bject.getOwnPropertyDescriptors方法的另一个用处,是配合Object.create方法,将对象属性克隆到一个新对象。这属于浅拷贝
const clone = Object.create(Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj));
// 或者
const shallowClone = (obj) => Object.create(
Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj)
);
vue里面怎么实现双向绑定?
Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptor()
Object.defineProperties()
Object.defineProperty()
扩展
https://segmentfault.com/a/1190000011294519#articleHeader18
面向对象扩展
https://segmentfault.com/a/1190000015377875
其它Object其它方法自己看
找机会单独分享,小伙伴也可以毛遂自荐
[JavaScript——原型:prototype、constructor、proto]
Object.getPrototypeOf()
Object.setPrototypeOf()
Object.create()
Object.getOwnPropertySymbols
super 关键字
(https://segmentfault.com/a/1190000012446557)
网友评论