本篇將講解js對象的存取器,介紹兩個重要的對象方法
為什么vue不兼容IE8匈勋,因為IE8不兼容ESMAScript5包帚,Vue會將對象所有的屬性遍歷,使用Object.defineProperty把這些屬性全部轉(zhuǎn)為getter/setter.(存儲器)
在ES5中镊叁,對象的屬性值可以用一個或兩個方法代替,這兩個方法就是getter和setter走触,由getter和setter定義的屬性被稱為存取器屬性
晦譬,它不同于數(shù)據(jù)屬性,數(shù)據(jù)屬性只有一個簡單的值
當(dāng)我們查詢存取器屬性的值時互广,JavaScript調(diào)用getter方法(無參數(shù))敛腌。這個方法的返回值就是屬性存取表達(dá)式的值,將賦值表達(dá)式返回的值當(dāng)成參數(shù)傳入setter
我們之前提過對象的屬性特性惫皱,比如可寫可讀像樊,如果一個屬性同事時具有g(shù)etter|和setter方法,那么這個屬性就是一個讀/寫屬性旅敷,如果只有g(shù)etter 只有setter 就曉得了吧
getter和setter
我們簡單來看看如何使用
var obj = {
get p() {
return 'getter';
},
set p(value) {
console.log('setter: ' + value);
return value
}
}
console.log(obj.p) //getter
console.log(obj.p=20) //setter:20
從這里我們能看出生棍,首先調(diào)用屬性會觸發(fā)對象的getter方法,設(shè)置屬性會觸發(fā)對象的setter方法媳谁,而且setter方法是可以全局操作的涂滴,我們看下面這個例子
var b=10
var that=this
var obj = {
get p() {
return 'getter';
},
set p(value) {
that.b=value
return value
}
}
obj.p=20
console.log(b)//20
最簡單的運用
var a={
_age:18,//通過改變age判斷方法的觸發(fā)
get age(){
console.log('get')
return this._age //getter方法沒有參數(shù)
},
set age(val){ //參數(shù)就是我們改變數(shù)據(jù)的操作
console.log('set')
return this._age=val
}
}
console.log(a.age) //18 get
a.age=21
console.log(a.age) //21 set
我們再來聊聊對象的屬性特性,對象的四個特性晴音,可讀性(value)柔纵,可寫性(writable),可枚舉性(enumerable)锤躁,可配置性(configurable)搁料,這幾個單詞可以稍微加點印象,指不定哪天你在瀏覽文檔的時候就能翻到這幾個單詞系羞,比如undefined
我們之前就說過加缘,undefined是JavaScript的一個全局屬性
好,任何一個對象都有以上的屬性觉啊,Object也為我們提供了方法用來判斷
var a={x:1}
var b = Object.getOwnPropertyDescriptor(a,'x')
console.log(b) //{value: 1, writable: true, enumerable: true, configurable: true}
我們用存取器試試
var a={
_age:18,//通過改變age判斷方法的觸發(fā)
get age(){
console.log('get')
return this._age //getter方法沒有參數(shù)
},
set age(val){ //參數(shù)就是我們改變數(shù)據(jù)的操作
console.log('set')
return this._age=val
}
}
console.log(Object.getOwnPropertyDescriptor(a,'age')) //{set: undefined, enumerable: true, configurable: true, get: ?}
如果未設(shè)置getter setter方法對應(yīng)的就是undefined拣宏,相當(dāng)于get代替了value,set代替了writable杠人,繼承的屬性或者是不存在的屬性都將返回undefined勋乾,了解一下
接下來我們講一下對象兩個重要的方法,雖然說重要不過可能很多小伙伴沒見過
Object.defineProperties()和Object.defineProperty()
這兩個方法有點像哈嗡善,英語小王子一眼就能看出來單復(fù)數(shù)了哈
Object的defineProperty和defineProperties這兩個方法在js中的重要性十分重要辑莫,主要功能就是用來定義或修改這些內(nèi)部屬性,與之相對應(yīng)的getOwnPropertyDescriptor和getOwnPropertyDescriptors就是獲取這行內(nèi)部屬性的描述。后面兩個就不多做描述了
我們都知道vue雙向綁定原理就是Object.definePriperty()方法罩引,我們先看看Object.defineProperties()各吨,今天將以實現(xiàn)簡單的雙向綁定原理結(jié)束(還好今天UI小姐姐沒讓我改bug)
Object.definProperties()
功能:
方法直接在一個對象上定義一個或多個新的屬性或修改現(xiàn)有屬性,并返回該對象袁铐。
語法: Object.defineProperties(obj, props)
obj: 將要被添加屬性或修改屬性的對象
props: 該對象的一個或多個鍵值對定義了將要為對象添加或修改的屬性的具體配置(簡單來說就是映射表---看代碼就懂)
var obj = new Object();
Object.defineProperties(obj, {
name: {
value: '張三',
configurable: false,
writable: true,
enumerable: true
},
age: {
value: 18,
configurable: true
}
})
console.log(obj.name, obj.age) // 張三, 18
很容易理解哈揭蜒,然后我們看到我給age只設(shè)置了兩個屬性横浑,可讀可配置,我們來改一下看看行不行
var obj = new Object();
Object.defineProperties(obj, {
name: {
value: '張三',
configurable: false,
writable: true,
enumerable: true
},
age: {
value: 18,
configurable: true
}
})
obj.age=20
console.log(obj.age) // 18 很明顯這是不可以滴
我們使用Object.getOwnPropertyDescriptor()方法看看屬性特性
var obj = new Object();
Object.defineProperties(obj, {
name: {
value: '張三',
configurable: false,
writable: true,
enumerable: true
},
age: {
value: 18,
configurable: true
}
})
var person = {
name: '張三',
age: 18
}
var desc = Object.getOwnPropertyDescriptor(obj, 'age');
console.log(desc) //obj.html:33 {value: 18, writable: false, enumerable: false, configurable: true}
沒配置的為false
var person = {
name: '張三',
age: 18
}
var desc = Object.getOwnPropertyDescriptor(person, 'age');
console.log(desc) //{value: 18, writable: true, enumerable: true, configurable: true}
我們常用的對象操作屉更,默認(rèn)屬性都是true
之前介紹了delete 刪除對象屬性徙融,也就是configurable為ture是可以刪除的
delete obj.age
console.log(obj.age) //undefined 嚴(yán)格模式下出錯 非嚴(yán)格模式下可以運行
那么Object.defineProperties(obj, props)也是可以使用存取器了
var obj = new Object();
Object.defineProperties(obj, {
name: {
value: '張三',
configurable: false,
writable: true,
enumerable: true
},
age: {
value: 18,
configurable: true
},
sex:{
get(){
return 'nan'
}
}
})
console.log(obj.sex) // nan
當(dāng)然也是可以配置屬性特性
sex:{
get(){
return 'nan'
},
configurable: false,
writable: true,
enumerable: true
}
這個方法還是很強(qiáng)大的,我們可以根據(jù)需要更改特性瑰谜,比如下方這個例子
var obj={
c:10
}
Object.defineProperties(obj, {
name: {
value: '張三',
configurable: false,
writable: true,
enumerable: true
},
age: {
value: 18,
configurable: true
},
c:{
writable:false
}
})
obj.c=20
console.log(obj.c) // 10 設(shè)置成無法修改了
Object.defineProperty()
功能:
方法會直接在一個對象上定義一個新屬性欺冀,或者修改一個對象的現(xiàn)有屬性, 并返回這個對象萨脑。如果不指定configurable, writable, enumerable 隐轩,則這些屬性默認(rèn)值為false,如果不指定value, get, set渤早,則這些屬性默認(rèn)值為undefined
語法:Object.defineProperty(obj, prop, descriptor)
obj: 需要被操作的目標(biāo)對象
prop: 目標(biāo)對象需要定義或修改的屬性的名稱
descriptor: 將被定義或修改的屬性的描述符
var obj={
c:10
}
Object.defineProperties(obj, {
name: {
value: '張三',
configurable: false,
writable: true,
enumerable: true
},
age: {
value: 18,
configurable: true
},
c:{
writable:false
}
})
Object.defineProperty(obj,'c',{value:20})
console.log(obj.c) //20
這樣就可以更改值了职车,哪怕你是不可寫的,當(dāng)然這是在可配置的情況下
c:{
writable:false,
configurable: false
}
如果是不可配置的蛛芥,就會報錯注意一下
Object.defineProperty配置的對象是不可枚舉的
var obj={
}
Object.defineProperty(obj,'c',{value:20})
for(var index in obj){
console.log(index) // kong
}
console.log(obj.c)// 20
但是可以取到這個屬性哦
var obj={
c:10
}
Object.defineProperty(obj,'c',{writable:false})
obj.c=20
console.log(obj.c)// 10
很多方法在嚴(yán)格模式下是會報錯的提鸟,如果我們已經(jīng)設(shè)置了不可寫做出修改操作,在嚴(yán)格模式下會報錯仅淑,這三個參數(shù)都是必填称勋,第三個參數(shù)寫個{}也行,不能不寫
兩種方法還是很類似的涯竟,當(dāng)然啦 也有這兩種方法沒辦法為所欲為的時候赡鲜,簡單介紹一下對象的屬性
原型屬性
這個我們快速過,之前我們講的Object.create()就是很好的代表
類屬性
對象的類屬性是個字符串庐船,用來表示對象的類型信息银酬,然而ES3與ES5都未設(shè)置這個屬性的方法,有一種間接的方法可以查詢到它
function classof(obj){
if(obj==null){
return 'Null'
}
if(obj==undefined){
return "Undefined"
}
return Object.prototype.toString.call(obj).slice(8,-1) //字符串過濾
}
console.log(classof(null)) //Null
console.log(classof(1)) //Number
console.log(classof("")) //String
console.log(classof(false)) //Boolean
console.log(classof(/./)) //RegExp
toString() 是 Object 的原型方法筐钟,調(diào)用該方法揩瞪,默認(rèn)返回當(dāng)前對象的 [[Class]] 。這是一個內(nèi)部屬性篓冲,其格式為 [object Xxx] 李破,其中 Xxx 就是對象的類型。我把前面的內(nèi)容去了更明了
可擴(kuò)展性
對象的可擴(kuò)展性用以表示是否可以給對象添加新屬性壹将,非常強(qiáng)悍嗤攻,之前提到的兩個方法在這里只有瑟瑟發(fā)抖的份
var a={
b:10
}
console.log(Object.isExtensible(a)) //true
如果為true表明是可擴(kuò)展的
我們強(qiáng)力改變讓它不可擴(kuò)展
var a={
b:10
}
Object.preventExtensions(a)
console.log(Object.isExtensible(a)) //false
擴(kuò)展性用以表示是否可以給對象添加新屬性
var a={
b:10
}
a.c=20
console.log(a.c) //20
Object.preventExtensions(a)
a.d=30
console.log(a.d) //undefined
我們使用defineProperty嘗試一下
var a={
b:10
}
a.c=20
console.log(a.c) //20
Object.preventExtensions(a)
a.d=30
Object.defineProperty(a,'e',{value:40})
console.log(a.d) //undefined
console.log(a.e) //報錯 對象不可擴(kuò)展
可擴(kuò)展性屬性的目的是將對象鎖定,防止外界的干擾诽俯,不過如果是繼承的屬性就沒法拒絕妇菱,爸爸給的東西不管好的壞的都得乖乖受著
簡單介紹一下可擴(kuò)展性,有興趣的可以去了解一下Object.seal()封閉,Object.freeze()凍結(jié)闯团,更兇殘
序列化對象
簡單提一下辛臊,序列化對象是指將對象的狀態(tài)轉(zhuǎn)成字符串,也可將字符串還原為對象偷俭。
就是我們常用的JSON.strstringify()和JSON.parse()轉(zhuǎn)字符串和轉(zhuǎn)對象
JSON的全稱就是 “JavaScript Object Notation”---------JavaScript對象表示法
我們寫個簡易的雙向綁定結(jié)束這篇js對象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Cache-Control" content="max-age=31536000">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<p>
<input type="text" id="input1">
</p>
<p>
<input type="text" id="input2">
</p>
</body>
<script>
var oIn1 = document.getElementById('input1');
var oIn2 = document.getElementById('input2');
var obj = {};
Object.defineProperties(obj, { //我這邊用的是defineProperties 因為網(wǎng)上大多都是defineProperty 希望小伙伴有個區(qū)別
val1: {
configurable: true,
get: function() {
oIn1.value = ''; //初始定義 為空
oIn2.value = '';
return ''
},
set: function(newValue) { // val1 改變的時候 給oIn2賦值
oIn2.value = newValue;
}
},
val2: {
configurable: true,
get: function() {
oIn1.value = '';
oIn2.value = '';
return ''
},
set: function(newValue) {
oIn1.value = newValue;
}
}
})
oIn1.value = obj.val1; //調(diào)用getter 初始為''
oIn1.oninput=function(){ //input事件不懂的可以百度一下
obj.val1 = oIn1.value; //觸發(fā)set給in2賦值
}
oIn2.oninput=function(){
obj.val2 = oIn2.value;
}
</script>
</html>
希望你可以理解浪讳,不懂歡迎留言