容許直接寫入變量和函數做爲對象屬性和方法html
let birth = '2000/01/01';
const Person = {
name: '張三',
//等同於birth: birth
birth,
// 等同於hello: function ()...
hello() { console.log('個人名字是', this.name); }
};
複製代碼
在ES5中,字面量方式定義對象時,不可使用表達式做爲屬性名。ES6字面量定義對象時容許這種方式,也就是將表達式放在方括號內,也能夠定義方法名。es6
let lastWord = 'last word';
const a = {
'first word': 'hello',
[lastWord]: 'world',
['h' + 'ello']() {
return 'hi';
}
};
console.log(a['first word']); // "hello"
console.log(a[lastWord]); // "world"
console.log(a['last word']); // "world"
console.log(a.hello()); // hi
console.log(a['last word']); // "world"
複製代碼
方法的name屬性返回函數名web
const person = {
sayName() {
console.log('hello!');
},
};
person.sayName.name // "sayName"
複製代碼
特殊狀況:數組
const obj = {
get foo() {},
set foo(x) {}
};
obj.foo.name
// TypeError: Cannot read property 'name' of undefined
const descriptor = Object.getOwnPropertyDescriptor(obj, 'foo');
descriptor.get.name // "get foo"
descriptor.set.name // "set foo"
複製代碼
(new Function()).name // "anonymous"
var doSomething = function() {
// ...
};
doSomething.bind().name // "bound doSomething"
複製代碼
對象每一個屬性都有描述對象,描述對象有enumerable屬性,稱可枚舉性,若是屬性爲false,表示不可枚舉。bash
四個忽略enumerable爲false屬性的操做 1.for...in循環;Object.keys();JSON.stringify();Object.assign()(ES6新增)dom
(1) for...in:遍歷對象自身和繼承的可枚舉屬性(不含Symbol屬性)ide
(2) Object.keys(obj):返回數組,包括對象自身的(不含繼承的)全部可枚舉屬性(不含 Symbol 屬性)的鍵名。函數
(3) Object.getOwnPropertyNames(obj返回一個數組,包含對象自身的全部屬性(不含 Symbol 屬性,可是包括不可枚舉屬性)的鍵名。優化
(4) Object.getOwnPropertySymbols(obj):返回一個數組,包含對象自身的全部 Symbol 屬性的鍵名。ui
(5) Reflect.ownKeys(obj):返回一個數組,包含對象自身的全部鍵名,無論鍵名是 Symbol 或字符串,也無論是否可枚舉。
super關鍵字指向當前對象的原型對象,super表示原型對象時,只能用在對象的方法中。
const proto = {
foo: 'hello'
};
const obj = {
foo: 'world',
find() {
return super.foo;
}
};
Object.setPrototypeOf(obj, proto);
console.log(obj.find()); // "hello"
複製代碼
用於取出對象理全部可遍歷的屬性,拷貝到當前對象。
let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }
複製代碼
擴展運算符等同於使用Object.assign(),只拷貝對象實例的屬性
let aClone = { ...a };
// 等同於
let aClone = Object.assign({}, a);
複製代碼
擴展運算符能夠用於合併兩個對象。
let ab = { ...a, ...b };
// 等同於
let ab = Object.assign({}, a, b);
複製代碼
若是用戶自定義的屬性,放在擴展運算符後面,則擴展運算符內部的同名屬性會被覆蓋掉。方便修改對象部分現有屬性。
let aWithOverrides = { ...a, x: 1, y: 2 };
// 等同於
let aWithOverrides = { ...a, ...{ x: 1, y: 2 } };
// 等同於
let x = 1, y = 2, aWithOverrides = { ...a, x, y };
// 等同於
let aWithOverrides = Object.assign({}, a, { x: 1, y: 2 });
複製代碼
若是把自定義屬性放在擴展運算符前面,就變成了設置新對象的默認屬性值。
let aWithDefaults = { x: 1, y: 2, ...a };
// 等同於
let aWithDefaults = Object.assign({}, { x: 1, y: 2 }, a);
// 等同於
let aWithDefaults = Object.assign({ x: 1, y: 2 }, a);
複製代碼
其餘特色可參照數組的擴展運算符。
用於從一個對象取值
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
複製代碼
參照前面解構賦值
比較兩個值是否嚴格相等,與===行爲基本一致,不一樣之處在於:===中,+0等於-0,NaN不等於自身。
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
複製代碼
用於將全部可枚舉屬性的值從一個或多個源對象複製到目標對象。返回目標對象。
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
複製代碼
const v1 = 'abc';
const v2 = true;
const v3 = 10;
const obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
複製代碼
Object.assign({ a: 'b' }, { [Symbol('c')]: 'd' })
// { a: 'b', Symbol(c): 'd' }
複製代碼
const target = { a: { b: 'c', d: 'e' } }
const source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }
複製代碼
Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]
複製代碼
Object.assign把數組視爲屬性名爲 0、一、2 的對象,所以源數組的 0 號屬性4覆蓋了目標數組的 0 號屬性1。 10. Object.assign只能進行值的複製,若是要複製的值是一個取值函數,那麼將求值後再複製。
const source = {
get foo() { return 1 }
};
const target = {};
Object.assign(target, source)
// { foo: 1 }
複製代碼
source對象的foo屬性是一個取值函數,Object.assign不會複製這個取值函數,只會拿到值之後,將這個值複製過去。
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}
複製代碼
Object.assign(obj, {
someMethod(arg1, arg2) {
···
},
anotherMethod() {
···
}
});
複製代碼
Object.assign({}, origin);
複製代碼
Object.assign(target, ...sources);
複製代碼
const DEFAULTS = {
logLevel: 0,
outputFormat: 'html'
};
function processContent(options) {
options = Object.assign({}, DEFAULTS, options);
}
複製代碼
用來獲取一個對象的==全部==自身屬性的描述符。參數爲任意對象。
解決了Object.assign()沒法正確拷貝get和set屬性的問題。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 }
複製代碼
配合Object.create()方法,將對象屬性克隆到新對象(淺拷貝)
const clone = Object.create(Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj));
複製代碼
實現一個對象繼承另外一個對象
const obj = Object.create(
prot,
Object.getOwnPropertyDescriptors({
foo: 123,
})
);
複製代碼
返回一個數組,成員是參數對象自身的(不含繼承的)全部可遍歷(enumerable)屬性的鍵名。
參數:obj-要返回其枚舉自身屬性的對象
返回一個數組,成員是參數對象自身的(不含繼承的)全部可遍歷(enumerable)屬性的鍵值。
參數:obj-要返回其枚舉自身屬性鍵值的對象
返回一個數組,成員是參數對象自身的(不含繼承的)全部可遍歷(enumerable)屬性的鍵值對數組。
參數:obj-能夠返回其可枚舉屬性的鍵值對的對象。
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]
}
複製代碼
會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 並返回這個對象。
參數:
(1)obj-要在其上定義屬性的對象
(2)prop-要定義或修改屬性的名稱
(3)descriptor-將被定義或修改的屬性描述符
descriptor能夠設置的值有
實際運用
優化對象獲取和修改屬性的方式
//加入有一個目標節點, 想設置其位移
var targetDom = document.getElementById('target');
var transformText = 'translateX(' + 10 + 'px)';
targetDom.style.webkitTransform = transformText;
targetDom.style.transform = transformText;
// 用defineProperty方法優化
Object.defineProperty(dom, 'translateX', {
set: function(value) {
var transformText = 'translateX(' + value + 'px)';
dom.style.webkitTransform = transformText;
dom.style.transform = transformText;
}
//這樣再後面調用的時候, 十分簡單
dom.translateX = 10;
dom.translateX = -10;
複製代碼
MVVM中數據‘雙向綁定’實現
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>標題</title>
</head>
<body>
<h3>使用Object.defineProperty實現簡單的雙向數據綁定</h3>
<input type="text" id="input" />
<div id="div"></div>
<script>
var obj = {};
var inputVal = document.getElementById("input");
var div = document.getElementById("div");
Object.defineProperty(obj, "name", {
set: function(newVal) {
inputVal.value = newVal;
div.innerHTML = newVal;
}
});
inputVal.addEventListener('input', function(e){
obj.name = e.target.value;
});
</script>
</body>
</html>
複製代碼
封閉一個對象,阻止添加新屬性並將全部現有屬性標記爲不可配置, 當前屬性的值只要可寫就能夠改變。
參數:obj-要被密封的對象
// 若是屬性值可寫
let obj = Object.defineProperty({},'name',{
value:'hello',
writable:true
})
Object.seal(obj);
console.log(obj.name); // hello
obj.name = 'world';
delete obj.name;
console.log(obj.name); // world
// 若是屬性值不可寫
let obj = Object.defineProperty({},'name',{
value:'hello',
writable:false,
})
Object.seal(obj);
console.log(obj.name); // hello
obj.name = 'world';
delete obj.name;
console.log(obj.name); // hello
複製代碼
能夠凍結一個對象。一個被凍結的對象不再能被修改;凍結了一個對象則不能向這個對象添加新的屬性,不能刪除已有屬性,不能修改該對象已有屬性的可枚舉性、可配置性、可寫性,以及不能修改已有屬性的值。此外,凍結一個對象後該對象的原型也不能被修改。
參數:obj-要被凍結的對象
let obj = Object.defineProperty({},'name',{
value:'hello',
writable:true
})
Object.freeze(obj);
console.log(obj.name); // hello
obj.name = 'world';
delete obj.name;
console.log(obj.name); // hello
複製代碼
摘自阮一峯
參照MDN