基本擴展
允許使用已有對象賦值定義對象字面量,并且只寫變量名即可
var name = "Bob"; var getName = function(){console.log(this.name);}; var person = {name, getName}; //相當于 //var person = { //name: "Bob", //getName: function(){console.log(this.name);} //} person.getName(); //"Bob"
可以像定義存取器那樣定義方法
var o = { _age: 10, _score: 60, age(num){ if(num > 0) { this._age = num; return this; } return this._age; }, get score(){ return this._score; } }; console.log(o.age()); //10 o.age(15); console.log(o.age()); //15 console.log(o.score); //60 o.score = 100; //TypeError
注意,以下代碼是等同的:
var obj = { class () {} //并不會因為 class 是關鍵字而解析錯誤 }; //等價于 var obj = { "class": function() {} };
如果一個方法是 Generator 函數,需要在前面加 *:
var obj = { time: 1, *gen(){ yield "hello " + time; time++; } }
屬性名表達式
js 本來可以這樣 obj["k"+"ey"] 訪問一個對象屬性,現在也可以這樣定義屬性了:
var key1 = "name"; var key2 = "age"; var o = { [key1]: "Bob", [key2]: 18, ["first" + key1]: "Ellen" }; o.name; //"Bob" o.age; //18 o.firstname; //"Ellen"
注意:該方法不能和上一小節使用已有標識符定義對象字面量的方法混合使用,否則會報錯;
//錯誤用法 var foo = "bar"; var bar = "abc"; var baz = {[foo]}; //報錯
方法的 name 屬性
函數有 name 屬性,方法也就有 name 屬性。一般方法 name 返回函數名(不包括對象名),對于存取器方法,沒有 name 屬性:
var o = { _age: 10, _score: 60, _name: "Bob", _firstname: "Ellen", set age(num){ if(num > 0) { this._age = num; return this; } }, get age(){ return this._age; }, get score(){ return this._score; }, name(n){ if(!n) return this._name + " " + this._firstname; this._name = n; return this; }, set firstname(n){ if(n) this._firstname = n; return this; } }; console.log(o.name.name); //"name" console.log(o.age.name); //undefined console.log(o.score.name); //undefined console.log(o.firstname); //undefined,所以 set 函數更不會有 name 屬性
如果對象的方法是個 symbol,name 屬性為空字符串 "" :
var sym1 = new Symbol("description of sym1"); var sym2 = new Symbol(); var o = { [sym1](){}, [sym2](){}, }; o[sym1].name; //"" o[sym2].name; //""
靜態方法
Object.is(a,b): 比較a,b兩個值是否嚴格相等,相當于 ===, 但有一點不一樣:
-0 === +0; //true NaN === NaN; //false Object.is(-0, +0); //false Object.is(NaN, NaN); //true
Object.assign(target, source1,source2,...): 將每個 source 對象自身的可枚舉屬性復制到 target 對象上,不包括原型鏈上的屬性和不可枚舉屬性。只有有一個參數不是對象,就會拋出 TypeError 錯誤。遇到同名屬性,排在后面的會覆蓋前面的:
var target = {a:1,b:2}; var source1 = {a:3,c:3}; var source2 = {a:2,d:0}; Object.assign(target, source1, source2); console.log(target); //{a: 2, b: 2, c: 3, d: 0}
對于屬性名是 symbol 的可枚舉屬性也會被復制:
Object.assign({a:"b"}, {[Symbol("c")]:"d"}); //{a: "b", Symbol(c): "d"}
對于同名屬性存在嵌套對象,外層會被直接替換:
Object.assign({a:{b:"c",d:"e"}}, {a:{b:"hello"}}); //{a:{b:"hello"}}
可以用 Object.assign處理數組,但會視其為對象:
Object.assign([1,2,3], [4,5]); //[4, 5, 3]
技巧:為對象添加屬性方法
Object.assign(String.prototype, { newProperty: "value", newFunction: function(){} })
技巧:克隆對象
Object.assign({},origin);
技巧:為對象添加屬性方法
Object.assign(target, ...source);
技巧:為對象添加屬性方法
const DEFAULT_OPTION = { //默認值 a: 1, b: 2 }; function processContent(newOption){ return Object.assign({}, DEFAULT_OPTION, newOption); } //設置屬性應該是基本類型,否則會因為深拷貝出問題對象屬性的可枚舉性與遍歷
以下6個操作會忽略不可枚舉的屬性
for...in循環
Object.keys()
JSON.stringify()
Object.assign()
Reflect.enumerate()
擴展運算符 ...
以下4個方法不忽略不可枚舉屬性
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Reflect.ownKeys()
以上9個方法中,只有2個會操作包含繼承到的屬性
for...in循環
Reflect.enumerate()
以上9個方法中,只有1個方法可以獲得 Symbol 屬性
Object.getOwnPropertySymbols()
除此之外需要強調的是 ES6 中,所有 class 的原型方法都是不可枚舉的:
Object.getOwnPropertyDescriptor(class{foo(){}}.prototype, foo).enumerable; //false
ES6 起,有了7中遍歷屬性的方法:
for...in: 循環遍歷對象自身和繼承到的可枚舉屬性,不包括 Symbol 屬性
Object.keys(obj): 返回包含自身可枚舉屬性的屬性名數組,不包含 Symbol 屬性
Object.getOwnPropertyNames(obj): 同上,但包括不可枚舉屬性
Object.getOwnPropertySymbols(obj): 返回自身所有 Symbol 屬性名的數組,包括不可枚舉屬性
Reflect.ownKey(obj): 返回自身所有屬性名數組,包括不可枚舉屬性和 Symbol 屬性名
Reflect.enumerate(): 返回一個 Iterator, 用來遍歷對象自身及繼承到的可枚舉屬性,不包括 Symbol 屬性;和 for...in 一樣
for...of: 只能遍歷具有 Iterator 接口的對象,具體作用范圍由 iterator 決定,遍歷沒有 iterator 的對象會報錯
以上方法除了 for...of 以外,遍歷順序為:
首先遍歷所有屬性名為數字的屬性,按數字大小排序;
其次遍歷所有屬性名為字符串的屬性,按屬性生成時間排序;
最后遍歷所有屬性名為 Symbol 的屬性,按屬性生成時間排序;
對象的__proto__屬性這是個很老很老的屬性,在大家想期待下,ES6終于把它寫進去了,嗯?...是寫進附錄了。這個屬性用來讀寫當前的對象的原型對象obj.constructor.prototype
從本質上來講,__proto__ 是定義在Object.prototype 上的一個存取器函數:
function isObject(a){ return Object(a) === a; } Object.defineProperty(Object.prototype, "__proto__", { get(){ let _thisObj = Object(this); return Object.getPrototypeOf(_thisObj); }, set(proto){ if(this == null) throw new TypeError(); if(!isObject(this) || !isObject(proto)) return undefined; let status = Object.setPrototypeOf(this, proto); if(! status) throw new TypeError(); } });
但是,還是不建議使用這個東西,畢竟看它這名字就是個內部屬性,因為它有了不加,但不保證所以終端都能用,所以ES6推薦用下面這兩個屬性:
Object.setPrototypeOf(obj, newProto); //寫 Object.getPrototypeOf(obj); //讀
簡單舉一個例子:
function Rectangle(){} var rec = new Rectangle(); Object.getPrototypeOf(rec) === Rectangle.prototype; //true Object.setPrototypeOf(rec, Object.prototype); Object.getPrototypeOf(rec) === Rectangle.prototype; //false
當然如果你把一個對象的原型設置成了 null, 也是可以的,只是,它不具備任何你聽說過的方法了:
var o = Object.setPrototypeOf({}, null); //等價于 var o = {"__proto__": null}; Object.getPrototypeOf(o); //null o.toString(); //TypeError: o.toString is not a function對象的擴展運算符
這是 ES7 的一個提案, babel可以使用器部分功能使用。
rest參數
用法和數組中很類似,這里不再過多贅述,直接看幾個例子吧:
var {x,y,...z} = {x: 1, y: 2, a: 3, d: 4}; //x=1, y=2, z={a: 3, d: 4}
值得強調的是, 對象的rest參數形式執行的是淺拷貝,賦值得到的是原對象的引用:
let obj = {a: {b: 1}}; let {...x} = obj; obj.a.b = 2; console.log(x.a.b); //2
此外 rest 不會復制不可枚舉屬性和繼承自原型的屬性:
var p = {a: 0}; var o = {b: 2}; var o = Object.defineProperty(o, "foo", { value: 2, configurable: true, enumerable: false, writable: true }); Object.setPrototypeOf(o, p); var u = { ...p }; console.log(u); //{b:2}
擴展運算符
復制參數對象所有可遍歷屬性到當前對象中:
var o1 = {a: 1, b: 2}; var n = { ...o1 }; //n={a: 1, b: 2}; //相當于 var n = Object.assign({}, o1);
可以用擴展運算符合并多個對象, 排后的屬性會覆蓋之前的屬性:
var source0 = {a:1,b:2}; var source1 = {a:3,c:3}; var source2 = {a:2,d:0}; Object.assign(target, source1, source2); var target = {...source0, ...source1, ...source2}; console.log(target); //{a: 2, b: 2, c: 3, d: 0}
注意一點:如果擴展運算符的參數對象有 get 方法,該方法會被執行:
var a = {o:1,p:2,m:4}; var withoutError = { ...a, get x(){ throw new Error(); } }; //不報錯 var withError = { ...a, ...{get x(){ throw new Error(); }} }; //報錯
如果擴展對象是 null 或 undefined,會被忽略,不報錯
var o = { ...null, ...undefined}; //不報錯 console.log(o); //{}
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97449.html
摘要:二進制和八進制表示法提供了二進制和八進制數值的新的寫法,分別用前綴或和或表示。用來檢查是否為有窮以及是否為這兩個新方法只對數值有效,非數值一律返回。引入了和這兩個常量,用來表示這個范圍的上下限。因為有精度限制,超過的次方的值無法精確表示。 1 二進制和八進制表示法 ES6提供了二進制和八進制數值的新的寫法,分別用前綴0b(或0B)和0o(或0O)表示。 console.log(0b10...
摘要:數值類型擴展類型新增了如下特性支持二進制和八進制二進制用或開頭八進制用或開頭新加方法判斷一個數字是否有限方法判斷一個變量是否。值得注意的是如果將非數值傳入這兩個函數一律返回。對于無法轉換為數值的參數返回符合函數。 數值類型擴展 Number 類型新增了如下特性: 支持二進制和八進制 二進制用 0b 或 0B 開頭, 八進制用 0o 或 0O 開頭: Number(0b1101); ...
摘要:屬性的簡潔表示法允許直接寫入變量和函數作為對象的屬性和方法。,中有返回一個數組,成員是參數對象自身的不含繼承的所有可遍歷屬性的鍵名。對象的擴展運算符目前,有一個提案,將解構賦值擴展運算符引入對象。 1 屬性的簡潔表示法 ES6允許直接寫入變量和函數作為對象的屬性和方法。 寫入屬性 var name = value; var obj = { name }; console.log...
摘要:原來的也被修改了數組實例的喝方法,用于找出第一個符合條件的數組成員。它的參數是一個回調函數,所有數組成員依次執行該回調函數,直到找出第一個返回值為的成員,然后返回該成員。數組實例的方法使用給定值,填充一個數組。 1 Array.from() Array.from方法用于將兩類對象轉為真正的數組:類似數組的對象(array-like object)和可遍歷(iterable)的對象(包括...
摘要:返回空字符串,返回將一個具名函數賦值給一個變量,則和的屬性都返回這個具名函數原本的名字。不可以使用對象,該對象在函數體內不存在。等到運行結束,將結果返回到,的調用幀才會消失。 1 函數參數的默認值 ES6允許為函數的參數設置默認值,即直接寫在參數定義的后面: function log(x = message.,y = duration infomation.) { consol...
閱讀 685·2023-04-25 22:50
閱讀 1525·2021-10-08 10:05
閱讀 983·2021-09-30 09:47
閱讀 1913·2021-09-28 09:35
閱讀 815·2021-09-26 09:55
閱讀 3405·2021-09-10 10:51
閱讀 3426·2021-09-02 15:15
閱讀 3290·2021-08-05 09:57