摘要:對象是中最常的內(nèi)置對象之一。為了節(jié)省內(nèi)存,使用一個共享的構(gòu)造器使用更安全的引用如果不是或,拋出一個異常。使創(chuàng)建的一個新的對象為,就和通過表達式創(chuàng)建一個新對象一樣,是標準內(nèi)置的構(gòu)造器名設(shè)置的內(nèi)部屬性為。方法返回一個該對象的字符串表示。
Object
對象是Javascript中最常的內(nèi)置對象之一。除了null 和 undefined,其他的所有的都可以轉(zhuǎn)換為對象??梢园褜ο罂闯珊墟I值一種數(shù)據(jù)結(jié)構(gòu),鍵稱為對象的屬性(只能是數(shù)字或者字符串),而值可以其他的任何類型。
例子對象是永遠引用類型
//對象是永遠引用類型,對象名指向內(nèi)存中的某個位置,而不是復制值。 var studentA = { name: "sundway" } var studentB = studentA; studentB.name = "modify"; console.log(studentA.name); // "modify" console.log(studentB.name); // "modify" /*studentA和studentB同時是對內(nèi)存中的一個引用,所以studentB.name的更改是對studentB.name和studentA.name的共同更改*/
對象的屬性只能是字符串或者數(shù)字。
var studentA = { "name": "sundway" //“name”可寫成name } var studentA = { 1 : "sundway" } console.log(studentA[1]); // 輸出"sundway"。 /*當屬性為數(shù)字時,不能通過.運算符去讀取屬性值,只能通過[]去讀取屬性值。*/
Javascript所有的都可以表現(xiàn)的像對象,但只有null 和 undefined比較特殊。
/*經(jīng)常會有這樣的誤解,數(shù)字字面量不能當作對象使用。其實主要原因Javascript解析器將數(shù)字后面和.運算符當成浮點類型的字面量。*/ 2.toString(); // Uncaught SyntaxError 2..toString(); // the second point is correctly recognized 2 .toString(); // note the space left to the dot (2).toString(); // 2 is evaluated first屬性
屬性描述符:屬性描述符有兩種主要形式,數(shù)據(jù)描述符(configurable、enumerable、value、writable)和存取描述(configurable、enumerable、get、set)符。數(shù)據(jù)描述符是一個擁有可寫或不可寫值的屬性。存取描述符是由一對 getter-setter 函數(shù)功能來描述的屬性。描述符必須是兩種形式之一;不能同時是兩者。(注:polymer和vue等庫底層貌似通過get和set實現(xiàn)雙向綁定)
Object.prototypeObject.prototype是一個原型對象,在JavaScript中,所有的對象都是基于 Object;所有的對象都繼承了Object.prototype的屬性和方法,它們可以被覆蓋(除了以null為原型的對象,如 Object.create(null));
Object.prototype.constructor返回一個指向創(chuàng)建了該對象原型的函數(shù)引用。需要注意的是,該屬性的值是那個函數(shù)本身,而不是一個包含函數(shù)名稱的字符串。
Object.prototype.__proto__一個對象的proto 屬性和自己的內(nèi)部屬性[[Prototype]]指向一個相同的值 (通常稱這個值為原型),原型的值可以是一個對象值也可以是null(比如說Object.prototype.proto的值就是null).該屬性可能會引發(fā)一些錯誤,因為用戶可能會不知道該屬性的特殊性,而給它賦值,從而改變了這個對象的原型. 如果需要訪問一個對象的原型,應(yīng)該使用方法Object.getPrototypeOf.
方法 Object.create ecma-262規(guī)范:Object.create ( O [ , Properties ] )
The create function creates a new object with a specified prototype. When the create function is called, the following steps are taken:
If Type(O) is neither Object nor Null, throw a TypeError exception.
Let obj be ObjectCreate(O).
If the argument Properties is present and not undefined, then
Return ObjectDefineProperties(obj, Properties).
Return obj.
Polyfill (基于Object.prototype.hasOwnProperty。)if(typeof Object.create != "function"){ Object.create = (function(){ //為了節(jié)省內(nèi)存,使用一個共享的構(gòu)造器 function Temp() {}; // 使用 Object.prototype.hasOwnProperty 更安全的引用 var hasOwn = Object.prototype.hasOwnProperty; return function (O) { // 1. 如果 O 不是 Object 或 null,拋出一個 TypeError 異常。 if (typeof O != "object") { throw TypeError("Object prototype may only be an Object or null"); } // 2. 使創(chuàng)建的一個新的對象為 obj ,就和通過 // new Object() 表達式創(chuàng)建一個新對象一樣, // Object是標準內(nèi)置的構(gòu)造器名 // 3. 設(shè)置 obj 的內(nèi)部屬性 [[Prototype]] 為 O。 Temp.prototype = O; var obj = new Temp(); Temp.prototype = null; // 不要保持一個 O 的雜散引用(a stray reference)... // 4. 如果存在參數(shù) Properties ,而不是 undefined , // 那么就把參數(shù)的自身屬性添加到 obj 上,就像調(diào)用 // 攜帶obj ,Properties兩個參數(shù)的標準內(nèi)置函數(shù) // Object.defineProperties() 一樣。 if (arguments.length > 1) { // Object.defineProperties does ToObject on its first argument. var Properties = Object(arguments[1]); for (var prop in Properties) { if (hasOwn.call(Properties, prop)) { obj[prop] = Properties[prop]; } } } // 5. 返回 obj return obj; }; })() }Object.is()
Object.is()[ES6]方法用來判斷兩個值是否是同一個值。
ecma-262規(guī)范:Object.is ( value1, value2 )
When the is function is called with arguments value1 and value2 the following steps are
taken:Return SameValue(value1, value2).
以上規(guī)范中最終返回SameValue(x, y),而ecma-262規(guī)范中對SameValue(x, y)規(guī)范是:
SameValue(value1, value2)
The internal comparison abstract operation SameValue(x, y), where x and y are ECMAScript language values, produces true or false. Such a comparison is performed as follows:ReturnIfAbrupt(x).
ReturnIfAbrupt(y).
If Type(x) is different from Type(y), return false.
If Type(x) is Undefined, return true.
If Type(x) is Null, return true.
If Type(x) is Number, then
If x is NaN and y is NaN, return true.
If x is +0 and y is ?0, return false.
If x is ?0 and y is +0, return false.
If x is the same Number value as y, return true.
Return false.
If Type(x) is String, then
If x and y are exactly the same sequence of code units (same length and same code units > at corresponding indices) return true; otherwise, return false.
If Type(x) is Boolean, then
If x and y are both true or both false, return true; otherwise, return false.
If Type(x) is Symbol, then
If x and y are both the same Symbol value, return true; otherwise, return false.
Return true if x and y are the same Object value. Otherwise, return false.
NOTE :This algorithm differs from the Strict Equality Comparison Algorithm (7.2.13) in its treatment of signed zeroes and NaNs.
上面提到這個算法和嚴格比較算法(===)有所不同,我們可以標出幾個不同的地方,然后在嚴格比較算法(===)的基礎(chǔ)上實現(xiàn)SameValue(value1, value2),同時也可以實現(xiàn)Object.is ( value1, value2 )。
Strict Equality Comparison
The comparison x === y, where x and y are values, produces true or false. Such a comparison > is performed as follows:
If Type(x) is different from Type(y), return false.
If Type(x) is Undefined, return true.
If Type(x) is Null, return true.
If Type(x) is Number, then
If x is NaN, return false.
If y is NaN, return false.
If x is the same Number value as y, return true.
If x is +0 and y is ?0, return true.
If x is ?0 and y is +0, return true.
Return false.
If Type(x) is String, then
If x and y are exactly the same sequence of code units (same length and same code units at corresponding indices), return true.
Else, return false.
If Type(x) is Boolean, thenIf x and y are both true or both false, return true.
Else, return false.
If x and y are the same Symbol value, return true.
If x and y are the same Object value, return true.
Return false.
比較SameValue(value1, value2) 和 Strict Equality Comparison,Strict Equality Comparison不能區(qū)分兩個不同的數(shù)字 -0 和 +0,還會把兩個 NaN 看成是不相等的。
Polyfill(基于===)Object.is = function(x, y) { // SameValue algorithm if (x === y) { // Steps 1-5, 7-10 // Steps 6.b-6.e: +0 != -0 return x !== 0 || 1 / x === 1 / y; } else { // Step 6.a: NaN == NaN return x !== x && y !== y; } };Object.assign ( target, ...sources )
Object.assign()[ES6] 方法可以把任意多個的源對象所擁有的自身可枚舉屬性拷貝給目標對象,然后返回目標對象。
PloyfillObject.assign ( target, ...sources )
The assign function is used to copy the values of all of the enumerable own properties from > one or more source objects to a target object. When the assign function is called, the >
following steps are taken:Let to be ToObject(target).
ReturnIfAbrupt(to).
If only one argument was passed, return to.
Let sources be the List of argument values starting with the second argument.
For each element nextSource of sources, in ascending index order,
If nextSource is undefined or null, let keys be an empty List.
Else,
Let from be ToObject(nextSource).
Let keys be from.[[OwnPropertyKeys]]().
ReturnIfAbrupt(keys).
Repeat for each element nextKey of keys in List order,
Let desc be from.[GetOwnProperty].
ReturnIfAbrupt(desc).
if desc is not undefined and desc.[[Enumerable]] is true, then
Let propValue be Get(from, nextKey).
ReturnIfAbrupt(propValue).
Let status be Set(to, nextKey, propValue, true).
ReturnIfAbrupt(status).
Return to.
The length property of the assign method is 2.
由于 ES5 里壓根就沒有 symbol 這種數(shù)據(jù)類型,所以這個 polyfill 也沒必要去支持 symbol 屬性(意思就是說,有 symbol 的環(huán)境一定有原生的 Object.assign):
if (!Object.assign) { Object.defineProperty(Object, "assign", { enumerable: false, configurable: true, writable: true, value: function(target, firstSource) { "use strict"; if (target === undefined || target === null) throw new TypeError("Cannot convert first argument to object"); var to = Object(target); for (var i = 1; i < arguments.length; i++) { var nextSource = arguments[i]; if (nextSource === undefined || nextSource === null) continue; var keysArray = Object.keys(Object(nextSource)); for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { var nextKey = keysArray[nextIndex]; var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); if (desc !== undefined && desc.enumerable) to[nextKey] = nextSource[nextKey]; } } return to; } }); }Demo
拷貝 symbol 類型的屬性
var o1 = { a: 1 }; var o2 = { [Symbol("foo")]: 2 }; var obj = Object.assign({}, o1, o2); console.log(obj); // Object {a: 1, Symbol(foo): 2}
繼承屬性和不可枚舉屬性是不能拷貝的
var obj = Object.create({foo: 1}, { // foo 是個繼承屬性。 bar: { value: 2 // bar 是個不可枚舉屬性。 }, baz: { value: 3, enumerable: true } }); var copy = Object.assign({}, obj); console.log(copy); // Object {baz: 3}
原始值會被隱式轉(zhuǎn)換成其包裝對象
var v1 = "123"; var v2 = true; var v3 = 10; var v4 = Symbol("foo") var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); // 源對象如果是原始值,會被自動轉(zhuǎn)換成它們的包裝對象, // 而 null 和 undefined 這兩種原始值會被完全忽略。 // 注意,只有字符串的包裝對象才有可能有自身可枚舉屬性。 console.log(obj); // { "0": "1", "1": "2", "2": "3" }
拷貝屬性過程中發(fā)生異常
var target = Object.defineProperty({}, "foo", { value: 1, writeable: false }); // target 的 foo 屬性是個只讀屬性。 Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4}); // TypeError: "foo" is read-only // 注意這個異常是在拷貝第二個源對象的第二個屬性時發(fā)生的。 console.log(target.bar); // 2,說明第一個源對象拷貝成功了。 console.log(target.foo2); // 3,說明第二個源對象的第一個屬性也拷貝成功了。 console.log(target.foo); // 1,只讀屬性不能被覆蓋,所以第二個源對象的第二個屬性拷貝失敗了。 console.log(target.foo3); // undefined,異常之后 assign 方法就退出了,第三個屬性是不會被拷貝到的。 console.log(target.baz); // undefined,第三個源對象更是不會被拷貝到的。Object.keys(obj)
Object.keys() 方法會返回一個由給定對象的所有可枚舉自身屬性的屬性名組成的數(shù)組,數(shù)組中屬性名的排列順序和使用for-in循環(huán)遍歷該對象時返回的順序一致(兩者的主要區(qū)別是 for-in 還會遍歷出一個對象從其原型鏈上繼承到的可枚舉屬性)。
Object.defineProperty(obj, prop, descriptor)Object.defineProperty() 方法直接在一個對象上定義一個新屬性,或者修改一個已經(jīng)存在的屬性, 并返回這個對象。
Object.defineProperties(obj, props)Object.defineProperties() 方法在一個對象上添加或修改一個或者多個自有屬性,并返回該對象。
Object.freeze(obj)Object.freeze() 方法可以凍結(jié)一個對象。也就是說,這個對象永遠是不可變的.
Object.isFrozen(obj)Object.isFrozen() 方法判斷一個對象是否被凍結(jié)(frozen)。ES5中規(guī)范和ES6有些不同:
If Type(O) is not Object throw a TypeError exception.(ES5)
If Type(O) is not Object, return true.(ES6)
所以O(shè)bject.isFrozen(1);在ES5中會報錯,而在ES6中會返回true.類似的還有Object.isExtensible()和Object.isSealed().
Object.preventExtensions(obj)Object.preventExtensions() 方法讓一個對象變的不可擴展,也就是永遠不能再添加新的屬性
Object.isExtensible(obj)Object.isExtensible() 方法判斷一個對象是否是可擴展的(是否可以在它上面添加新的屬性)
Object.seal(obj)bject.seal() 方法可以讓一個對象密封,并返回被密封后的對象。密封對象是指那些不能添加新的屬性,不能刪除已有屬性,以及不能修改已有屬性的可枚舉性、可配置性、可寫性,但可能可以修改已有屬性的值的對象。
Object.isSealed(obj)Object.isSealed() 方法判斷一個對象是否是密封的(sealed)。(密封對象是指那些不可 擴展 的,且所有自身屬性都不可配置的(non-configurable)對象。)
Object.getOwnPropertyDescriptor(obj, prop)Object.getOwnPropertyDescriptor() 返回指定對象上一個自有屬性對應(yīng)的屬性描述符。(自有屬性指的是直接賦予該對象的屬性,不需要從原型鏈上進行查找的屬性)
Object.getOwnPropertyNames(obj)Object.getOwnPropertyNames()方法返回一個由指定對象的所有自身屬性的屬性名(包括不可枚舉屬性)組成的數(shù)組。
Object.getOwnPropertySymbols(obj)Object.getOwnPropertySymbols()[ES6] 方法會返回一個數(shù)組,該數(shù)組包含了指定對象自身的(非繼承的)所有 symbol 屬性鍵。
Object.getPrototypeOf(obj)Object.getPrototypeOf()方法返回指定對象的原型。(也就是該對象內(nèi)部屬性[[prototype]]的值)
Object.observe(obj, callback)Object.observe()[ES7] 方法用于異步的監(jiān)視一個對象的修改。當對象屬性被修改時,方法的回調(diào)函數(shù)會提供一個有序的修改流。Object.observe().該方法在兩個月之前從提議中去掉了,可以使用第三方庫代替。
Object.unobserve(obj, callback)Object.unobserve()[ES7] 是用來移除通過 Object.observe()設(shè)置的觀察者的方法。
Object.getNotifer(obj)Object.getNotifer()[ES7]可以創(chuàng)造一個異步觸發(fā)的對象。
Object.prototype.toString()toString() 方法返回一個代表該對象的字符串。調(diào)用該對象的toString()方法時會返回"[object type]",這里的字符串type表示了一個對象類型。所以經(jīng)常使用該方法去做類型判斷,因為使用typeof,無法區(qū)分array, null, function, object等。因為該方法會被子類方法覆蓋,所以需要調(diào)用Object.prototype的toString()。
var toString = Object.prototype.toString; toString.call(new Function) // [object Function] toString.call(new Date); // [object Date] toString.call(new String); // [object String] toString.call(Math); // [object Math] //Since JavaScript 1.8.5 toString.call(undefined); // [object Undefined] toString.call(null); // [object Null]Object.prototype.toLocaleString();
toLocaleString() 方法返回一個該對象的字符串表示。該方法主要用于被本地化相關(guān)對象覆蓋。
Object.prototype.hasOwnProperty()hasOwnProperty() 方法用來判斷某個對象是否含有指定的自身屬性。
Object.prototype.isPrototypeOf(obj)isPrototypeOf() 方法測試一個對象是否存在于另一個對象的原型鏈上。
Object.prototype.propertyIsEnumerable(obj)propertyIsEnumerable() 方法返回一個布爾值,表明指定的屬性名是否是當前對象可枚舉的自身屬性.
Object.prototype.valueOf(obj)Object.prototype.valueOf()方法返回特定對象的初始值。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/78387.html
摘要:函數(shù)用于指定對象的行為。命名函數(shù)的賦值表達式另外一個特殊的情況是將命名函數(shù)賦值給一個變量。這是由于的命名處理所致,函數(shù)名在函數(shù)內(nèi)總是可見的。該方法返回一個表示當前函數(shù)源代碼的字符串。 函數(shù)包含一組語句,它們是JavaScript的基礎(chǔ)模塊單元,用于代碼的復用、信息隱藏和組合調(diào)用。函數(shù)用于指定對象的行為。一般來說,所謂編程,就是將一組需求分解成函數(shù)與數(shù)據(jù)結(jié)構(gòu)的技能。 JavaScript...
摘要:在很久之前讀過編程藝術(shù),現(xiàn)在重讀又有新的體會,遂記錄下。唯一沒有被其他元素包含的元素是元素,它是的根元素。是節(jié)點內(nèi)的第一個子節(jié)點,所以將是一個值,應(yīng)該寫成才能得到。操作操作無非是增刪改查,我們先看查和改。 在很久之前讀過JavaScript Dom 編程藝術(shù),現(xiàn)在重讀又有新的體會,遂記錄下。 什么是DOM 對于這種英文縮寫,首先看它的英文全拼--Document Object Mode...
摘要:定場詩馬瘦毛長蹄子肥,兒子偷爹不算賊,瞎大爺娶個瞎大奶奶,老兩口過了多半輩,誰也沒看見誰前言本章為重讀學習數(shù)據(jù)結(jié)構(gòu)與算法第三版的系列文章,主要講述隊列數(shù)據(jù)結(jié)構(gòu)雙端隊列數(shù)據(jù)結(jié)構(gòu)以及隊列相關(guān)應(yīng)用。 定場詩 馬瘦毛長蹄子肥,兒子偷爹不算賊,瞎大爺娶個瞎大奶奶,老兩口過了多半輩,誰也沒看見誰! 前言 本章為重讀《學習JavaScript數(shù)據(jù)結(jié)構(gòu)與算法-第三版》的系列文章,主要講述隊列數(shù)據(jù)結(jié)構(gòu)、...
摘要:第二種接口的概念和面向?qū)ο缶幊滔嚓P(guān)接口視為一份合約,在合約里可以定義這份合約的類或接口的行為接口告訴類,它需要實現(xiàn)一個叫做的方法,并且該方法接收一個參數(shù)。 定場詩 八月中秋白露,路上行人凄涼; 小橋流水桂花香,日夜千思萬想。 心中不得寧靜,清早覽罷文章, 十年寒苦在書房,方顯才高志廣。 前言 洛伊安妮·格羅納女士所著的《學習JavaScript數(shù)據(jù)結(jié)構(gòu)與算法》第三版于2019年的5月份...
摘要:如果是聲明中的第一個詞,那么就是一個函數(shù)聲明,否則就是一個函數(shù)表達式。給函數(shù)表達式指定一個函數(shù)名可以有效的解決以上問題。始終給函數(shù)表達式命名是一個最佳實踐。也有開發(fā)者干脆關(guān)閉了靜態(tài)檢查工具對重復變量名的檢查。 你不知道的JS(上卷)筆記 你不知道的 JavaScript JavaScript 既是一門充滿吸引力、簡單易用的語言,又是一門具有許多復雜微妙技術(shù)的語言,即使是經(jīng)驗豐富的 Ja...
閱讀 1948·2021-11-24 10:45
閱讀 1452·2021-11-18 13:15
閱讀 4524·2021-09-22 15:47
閱讀 3902·2021-09-09 11:36
閱讀 2006·2019-08-30 15:44
閱讀 3081·2019-08-29 13:05
閱讀 2495·2019-08-29 12:54
閱讀 1986·2019-08-26 13:47