摘要:屬性描述符升級(jí)打怪必備技能對(duì)象有自己的屬性和方法,對(duì)于我們對(duì)象的屬性來講,屬性還有自己的屬性,又稱為屬性描述符。這個(gè)方法接受三個(gè)參數(shù),第一個(gè)是指定的對(duì)象,第二個(gè)是指定的對(duì)象參數(shù),第三個(gè)當(dāng)然是要修改的屬性描述符了。
對(duì)象的聲明有倆種:
字面量
通過new一個(gè)構(gòu)造函數(shù)Object
兩者唯一的區(qū)別就是,字面量形式,可以一次賦值多個(gè),通過new Object就得一個(gè)一個(gè)賦值
數(shù)據(jù)類型
JS種7種數(shù)據(jù)類型
number
string
undefined
null
boolean
object
symbol(es6新增,也不算新了,es6都多久了...)
簡(jiǎn)單數(shù)據(jù)類型
number
string
undefined
null
boolean
復(fù)雜基本類型(內(nèi)置對(duì)象,object子類型)
Number
String
Boolean
Object
Function
Array
RegExp
Date
Error
補(bǔ)充:null為什么是基本類型但是依然會(huì)出現(xiàn),typeof null 會(huì)返回 object?這是一個(gè)語(yǔ)言的bug,原理如下:原理是這樣的,不同的對(duì)象在底層都表示為二進(jìn)制,在 JavaScript 中二進(jìn)制前三位都為 0 的話會(huì)被判
斷為 object 類型,null 的二進(jìn)制表示是全 0,自然前三位也是 0,所以執(zhí)行 typeof 時(shí)會(huì)返回“object”。
深入對(duì)比基本類型和復(fù)雜類型的區(qū)別,用string和String對(duì)比
var str = "hello world"; var strObj = new String("hello String"); str.length // 11 strObj.length // 12 // typeof判斷屬于那種簡(jiǎn)單數(shù)據(jù)類型 typeof str; // "string" typeof strObj; //"object" // instanceof判斷對(duì)象實(shí)例的鼻祖是哪個(gè)復(fù)雜類型 str instanceof String // false strObj instanceof String // true
這段代碼可以分析出,str通過字面量形式聲明,其數(shù)據(jù)類型為基本數(shù)據(jù)類型,并不是對(duì)象,strObj 為復(fù)雜數(shù)據(jù)類型String的實(shí)例。我們知道str, strObj的數(shù)據(jù)類型之后,就要拋出一個(gè)問題,為什么str并不是對(duì)象,它怎么就能調(diào)用length呢?這不是一個(gè)簡(jiǎn)單數(shù)據(jù)類型該有的呀。js向你丟出一個(gè)結(jié)論,那就是簡(jiǎn)單數(shù)據(jù)類型存在一個(gè)隱式轉(zhuǎn)換,它會(huì)從簡(jiǎn)單數(shù)據(jù)類型轉(zhuǎn)換為復(fù)雜數(shù)據(jù)類型。
對(duì)象 1. 對(duì)象的屬性首先以對(duì)象字面量整一個(gè)對(duì)象
let obj = { name: "hello", age: 12 }
訪問對(duì)象的屬性可以通過 圓點(diǎn)運(yùn)算符 類似于 obj.name, 還可以通過屬性運(yùn)算符 obj["name"]訪問。
2. 淺拷貝,深拷貝ES6 定義了Object.assign()方法實(shí)現(xiàn)淺復(fù)制,該方法第一個(gè)參數(shù)是目標(biāo)對(duì)象,之后還可以跟一個(gè)或多個(gè)原對(duì)象,他會(huì)遍歷一個(gè)或多個(gè)原對(duì)象所有可枚舉的自有鍵并把他們復(fù)制(使用 = 操作符賦值,所以這種僵硬的賦值操作,不會(huì)將原對(duì)象的屬性的特性復(fù)制過來)到目標(biāo)對(duì)象,最后返回目標(biāo)對(duì)象。
3. 屬性描述符【升級(jí)打怪必備技能】對(duì)象有自己的屬性和方法,對(duì)于我們js對(duì)象的屬性來講,屬性還有自己的“屬性”,又稱為屬性描述符。不要小看這個(gè)屬性描述符,可不得了,通過屬性描述符,我們不僅僅可以配置屬性是讀寫權(quán)限,甚至通過setter,getter實(shí)現(xiàn)我們的數(shù)據(jù)雙向綁定。該介紹一下這位調(diào)用屬性描述符的內(nèi)置方法了:Object.defineProperty()。這個(gè)方法接受三個(gè)參數(shù),第一個(gè)是指定的對(duì)象,第二個(gè)是指定的對(duì)象參數(shù),第三個(gè)當(dāng)然是要修改的屬性描述符了。當(dāng)對(duì)象中不存在指定的屬性,Object.defineProperty()就創(chuàng)建這個(gè)屬性,當(dāng)描述符中省略某些字段時(shí),這些字段將使用它們的默認(rèn)值,擁有布爾值的字段的默認(rèn)值都是false
所以這也就是說,通過Object.defineProperty()創(chuàng)建的屬性,描述符是不可配置的,因?yàn)閏onfigurable:false
// 直接對(duì)一個(gè)對(duì)象使用原點(diǎn)運(yùn)算符賦值,屬性描述符都是true var o = {}; o.a = 1; // 等同于 : Object.defineProperty(o, "a", { value : 1, writable : true, configurable : true, enumerable : true }); // 另一方面,使用Object.defineProperty()卻將屬性修飾符關(guān)閉了 Object.defineProperty(o, "a", { value : 1 }); // 等同于 : Object.defineProperty(o, "a", { value : 1, writable : false, configurable : false, enumerable : false });
var obj = { name: "hello", age: 12 } Object.defineProperty(obj, "name", { value: 2, writable: true, configurable: true, enumerable: true }) obj.name; //2 not hello
接下來,我們解釋一下屬性描述符的四大天王:value, writable, configurable, enumerable
configurable
為啥先要介紹configurable呢,不得不說說他的重要性,這個(gè)描述符的值是true/false,它表示屬性描述符是否可配置,當(dāng)值為false時(shí),剩下的描述符都是不可配置的,修改也不會(huì)生效,不包括value。簡(jiǎn)單的說,configurable控制的其他描述符的命運(yùn)!后面我們討論的時(shí)候,默認(rèn)configurable為true,不然,討論也沒有意義,根本不會(huì)改變嘛
var a = { name: "tom", age: 22 } Object.defineProperty(a, "age", { enumerable: false, writable:false, configurable: false, }) a.age = 12; // a.age 為12.即使writable 是false,因?yàn)閏onfigurable是false,所以writable其實(shí)還是默認(rèn)的true
我知道你肯定是不信的,直接上圖。Object.getOwnPropertyDescriptor() 與Object.defineProperty()互為一對(duì)兒,一個(gè)定義,一個(gè)查看定義
而且,將configurable修改為false,這是一個(gè)單向操作,你想再次修改它的值為true以實(shí)現(xiàn)重新配置屬性描述符是不可能的,一旦設(shè)置false,永遠(yuǎn)都是false了。聽說你還不信,那我再上圖
var myObject = { a:2 }; myObject.a = 3; myObject.a; // 3 Object.defineProperty( myObject, "a", { value: 4, writable: true, configurable: false, // 不可配置! enumerable: true } ); myObject.a; // 4 myObject.a = 5; myObject.a; // 5 Object.defineProperty( myObject, "a", { value: 6, writable: true, configurable: true, enumerable: true } ); // TypeError
writable
我們介紹一下控制讀寫的小伙伴-writable,這個(gè)屬性描述符控制我們是否可以對(duì)屬性進(jìn)行賦值,值為false時(shí),賦值是不管用的。嚴(yán)格模式下,還會(huì)拋出錯(cuò)誤。至于writable怎么處理屬性是否能被賦值,留一個(gè)疑問,稍后馬上揭曉。
// configurable為true var myObject = {}; Object.defineProperty( myObject, "a", { value: 2, writable: false, // 不可寫! configurable: true, enumerable: true } ); myObject.a = 3; myObject.a; // 2
Enumerable
這個(gè)屬性修飾符可能沒有那么直觀,但是從字面來看,我們應(yīng)該是能了解到的,這是控制屬性是否能出現(xiàn)在對(duì)象可枚舉屬性中。如果將enumerable設(shè)置為false,屬性就不會(huì)出現(xiàn)在可枚舉屬性中。enumerable定義了對(duì)象的屬性是否可以在 for...in 循環(huán)和 Object.keys() 中被枚舉。
var obj = { name: "tom", age: 12 } for(prop in obj) { console.log(prop); // name, age } Object.defineProperty(obj, "name", { enumerable: false, }) for(prop in obj) { console.log(prop); //age }
補(bǔ)充一些可枚舉相關(guān)的知識(shí),什么叫可枚舉屬性,就是指那些屬性描述符設(shè)置為enumerable為true的屬性。有很多方法是基于可枚舉性的。比如,Object.keys(), in, for in 。對(duì)于上面那個(gè)例子,就是使用了for in遍歷obj對(duì)象可枚舉屬性。
ES6 實(shí)現(xiàn)的常量const
本身JS是沒有常量這個(gè)概念的,但是我們可以使用writable:false 和 configurable:false,就可以創(chuàng)建一個(gè)一次賦值,不能修改的常量
禁止拓展
如果想禁止一個(gè)對(duì)象添加新屬性并且保留已有屬性,可以使用Object.preventExtensions(),這樣顯式賦值就會(huì)靜默失敗,嚴(yán)格模式下,將會(huì)拋出TypeError異常
密封,禁止拓展加強(qiáng)版,已有的屬性以及屬性修飾符都不能改
Object.seal(..) 會(huì)創(chuàng)建一個(gè)“密封”的對(duì)象,這個(gè)方法實(shí)際上會(huì)在一個(gè)現(xiàn)有對(duì)象上調(diào)用
Object.preventExtensions(..) 并把所有現(xiàn)有屬性標(biāo)記為 configurable:false。
所以,密封之后不僅不能添加新屬性,也不能重新配置或者刪除任何現(xiàn)有屬性(雖然可以
修改屬性的值)。
凍結(jié),更狠,Object.seal() 加強(qiáng)版,直接修改屬性修飾符writable:false,值都不能動(dòng)了。
Object.freeze(..) 會(huì)創(chuàng)建一個(gè)凍結(jié)對(duì)象,這個(gè)方法實(shí)際上會(huì)在一個(gè)現(xiàn)有對(duì)象上調(diào)用
Object.seal(..) 并把所有“數(shù)據(jù)訪問”屬性標(biāo)記為 writable:false,這樣就無法修改它們
的值。
ES5可以使用getter和setter部分改寫默認(rèn)操作,但是只能應(yīng)用在單個(gè)屬性上,無法應(yīng)用在整個(gè)對(duì)象上,getter,setter都是隱藏函數(shù),前者在獲取屬性值時(shí)自動(dòng)調(diào)用,后者是在設(shè)置屬性值時(shí)自動(dòng)調(diào)用。其實(shí)現(xiàn)在,我們可以總結(jié)一下前文所述。屬性描述符其實(shí)分為兩種
數(shù)據(jù)修飾符
訪問修飾符
而我們前文一直在講述數(shù)據(jù)修飾符,那么什么是訪問修飾符呢?
當(dāng)我們給一個(gè)屬性定義getter和setter或者兩者都有時(shí),這個(gè)屬性會(huì)被定義為”訪問描述符“,對(duì)于訪問描述符而言,JavaScript會(huì)忽略它們的value和writable特性,取而代之的是關(guān)心set/get(還有configurable和enumerable)特性
實(shí)例演示:
function Archiver() { var temperature = null; var archive = []; Object.defineProperty(this, "temperature", { get: function() { console.log("get!"); return temperature; }, set: function(value) { temperature = value; archive.push({ val: temperature }); } }); this.getArchive = function() { return archive; }; } var arc = new Archiver(); arc.temperature; // "get!" arc.temperature = 11; arc.temperature = 13; arc.getArchive(); // [{ val: 11 }, { val: 13 }]
一言以蔽之,setter/getter無非就是我們?cè)谫x值或者讀取變量時(shí),預(yù)先悄悄調(diào)用的一個(gè)隱藏方法。
還有一種通過對(duì)象文字語(yǔ)法創(chuàng)建的get,set(我也是從《你不知道的js》看到這種用法的,MDN這相關(guān)的文檔中我并沒有看到,學(xué)到了),這個(gè)不是通過Object.defineProperty()創(chuàng)建的,二者都會(huì)在對(duì)象中創(chuàng)建一個(gè)不包含值的屬性,對(duì)于這個(gè)屬性的訪問會(huì)自動(dòng)調(diào)用一個(gè)隱藏函數(shù),它的返回值會(huì)被當(dāng)作屬性訪問的返回值。
其實(shí)可以更細(xì)致的觀察到,通過對(duì)象文字語(yǔ)法創(chuàng)建的變量,他的修飾符按照規(guī)則肯定是沒有value的,但是其他配置信息是true,這一點(diǎn)很關(guān)鍵
大體上對(duì)象的內(nèi)容就是這么多,后續(xù)在做一個(gè)補(bǔ)充,MDN實(shí)在是前端寶典,看到這里更推薦讀者閱讀MDN相關(guān)文檔:https://developer.mozilla.org...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/108314.html
摘要:個(gè)人前端文章整理從最開始萌生寫文章的想法,到著手開始寫,再到現(xiàn)在已經(jīng)一年的時(shí)間了,由于工作比較忙,更新緩慢,后面還是會(huì)繼更新,現(xiàn)將已經(jīng)寫好的文章整理一個(gè)目錄,方便更多的小伙伴去學(xué)習(xí)。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 個(gè)人前端文章整理 從最開始萌生寫文章的想法,到著手...
摘要:當(dāng)然這還沒完,因?yàn)槲覀冞€有重要的一步?jīng)]完成,沒錯(cuò)就是上面的第行代碼,如果沒有這行代碼實(shí)例中的指針是指向構(gòu)造函數(shù)的,這樣顯然是不對(duì)的,因?yàn)檎G闆r下應(yīng)該指向它的構(gòu)造函數(shù),因此我們需要手動(dòng)更改使重新指向?qū)ο蟆? 第一節(jié)內(nèi)容:javaScript原型及原型鏈詳解(二) 第一節(jié)中我們介紹了javascript中的原型和原型鏈,這一節(jié)我們來講利用原型和原型鏈我們可以做些什么。 普通對(duì)象的繼承 ...
摘要:和的作用一樣,區(qū)別在于寫法語(yǔ)法對(duì)象對(duì)象作用判斷對(duì)象是否在對(duì)象的原型鏈上語(yǔ)法對(duì)象構(gòu)造函數(shù)作用判斷構(gòu)造函數(shù)的屬性是否在對(duì)象的原型鏈上,如果在,就返回屬性是否可枚舉用于檢查給定的屬性是否能夠使用語(yǔ)句。 ## javascript對(duì)象原型成員詳解 ## ECMAScript 中的對(duì)象就是一組數(shù)據(jù)和功能的集合,對(duì)象可以通過 new 操作符后跟要?jiǎng)?chuàng)建的對(duì)象名稱來...
摘要:理解的函數(shù)基礎(chǔ)要搞好深入淺出原型使用原型模型,雖然這經(jīng)常被當(dāng)作缺點(diǎn)提及,但是只要善于運(yùn)用,其實(shí)基于原型的繼承模型比傳統(tǒng)的類繼承還要強(qiáng)大。中文指南基本操作指南二繼續(xù)熟悉的幾對(duì)方法,包括,,。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。 怎樣使用 this 因?yàn)楸救藢儆趥吻岸?,因此文中只看懂?8 成左右,希望能夠給大家?guī)韼椭?...(據(jù)說是阿里的前端妹子寫的) this 的值到底...
摘要:作為構(gòu)造函數(shù)調(diào)用中沒有類,但是可以從構(gòu)造器中創(chuàng)建對(duì)象,并提供了運(yùn)算符來進(jìn)行調(diào)用該構(gòu)造器。構(gòu)造器的外表跟普通函數(shù)一樣,大部分的函數(shù)都可以當(dāng)做構(gòu)造器使用。如果構(gòu)造函數(shù)顯式的返回一個(gè)對(duì)象,那么則會(huì)指向該對(duì)象。 this 的指向 this 是 js 中定義的關(guān)鍵字,它自動(dòng)定義于每一個(gè)函數(shù)域內(nèi),但是它的指向卻讓人很迷惑。在實(shí)際應(yīng)用中,this 的指向大致可以分為以下四種情況。 1.作為普通函數(shù)調(diào)...
閱讀 4103·2021-09-22 10:02
閱讀 3435·2019-08-30 15:52
閱讀 3120·2019-08-30 12:51
閱讀 826·2019-08-30 11:08
閱讀 2132·2019-08-29 15:18
閱讀 3160·2019-08-29 12:13
閱讀 3663·2019-08-29 11:29
閱讀 1964·2019-08-29 11:13