欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解JavaScript常量定義

 更新時間:2017年01月03日 08:38:40   作者:DongXv  
本文主要對JavaScript常量定義進行詳細介紹,具有一定的參考價值,下面跟著小編一起來看下吧

相信同學(xué)們在看見這個標題的時候就一臉懵逼了,什么?JS能常量定義?別逗我好嗎?確切的說,JS當中確實沒有常量(ES6中好像有了常量定義的關(guān)鍵字),但是深入一下我們可以發(fā)現(xiàn)JS很多不為人知的性質(zhì),好好利用這些性質(zhì),就會發(fā)現(xiàn)一個不一樣的JS世界。

首先,在JS當中,對象的屬性其實還含有自己的隱含性質(zhì),比如下面對象:

var obj = {};
obj.a = 1;
obj.b = 2;

在這里我們定義了一個對象 obj ,并且定義了這個對象的兩個屬性 a 、 b ,我們可以修改這兩個屬性的值,可以用 delete 關(guān)鍵字刪除這兩個屬性,也可以用 for ... in ... 語句枚舉 obj 對象的所有屬性,以上的這些操作叫做對象屬性的性質(zhì),在我們平常編寫代碼的時候我們會不知不覺的默認了這些性質(zhì),把他們認作為JS應(yīng)有的性質(zhì),殊不知這些性質(zhì)其實是可以修改的。我通常的定義的屬性的方法,默認了屬性的性質(zhì),不過我們也可以在定義屬性的時候修改屬性的性質(zhì),比如:

var obj = {};
obj.a = 1;
obj.b = 2;
//等價于
var obj = {
 a: 1,
 b: 2
}
//等價于
var obj = {};
Object.defineProperty(obj, "a", {
 value: 1,    //初始值
 writable: true,  //可寫
 configurable: true, //可配置
 enumerable: true  //可枚舉
});
Object.defineProperty(obj, "b", {
 value: 2,    //初始值
 writable: true,  //可寫
 configurable: true, //可配置
 enumerable: true  //可枚舉
});

這里涉及到了一個方法,Object.defineProperty(),該方法是ES5規(guī)范中的,該方法的作用是在對象上定義一個新屬性,或者修改對象的一個現(xiàn)有屬性,并對該屬性加以描述,返回這個對象,我們來看一下瀏覽器兼容性:

特性 Firefox (Gecko) Chrome Internet Explorer Opera Safari
基本支持 4.0 (2) 5 9 [1] 11.60 5.1 [2]

還是天煞的IE8,如果你的項目要求兼容IE8,那么這個方法也就不適用了,不過IE8也對該方法進行了實現(xiàn),只能在DOM對象上適用,而且有一些獨特的地方,在這里就不講解了。

Object.defineProperty() 方法可以定義對象屬性的數(shù)據(jù)描述和存儲描述,這里我們只講數(shù)據(jù)描述符,不對存儲描述符講解,數(shù)據(jù)描述符有以下選項:

configurable
當且僅當該屬性的 configurable 為 true 時,該屬性描述符才能夠被改變,也能夠被刪除。默認為 false。
enumerable
當且僅當該屬性的 enumerable 為 true 時,該屬性才能夠出現(xiàn)在對象的枚舉屬性中。默認為 false。
value
該屬性對應(yīng)的值??梢允侨魏斡行У?JavaScript 值(數(shù)值,對象,函數(shù)等)。默認為 undefined。
writable
當且僅當該屬性的 writable 為 true 時,該屬性才能被賦值運算符改變。默認為 false。

注意,當我們用常規(guī)方法定義屬性的時候,其除 value 以外的數(shù)據(jù)描述符默認均為 true ,當我們用 Object.defineProperty() 定義屬性的時候,默認為 false。

也就是說,當我們把 writable 設(shè)置為 false 的時候,該屬性是只讀的,也就滿足了常量了性質(zhì),我們把常量封裝在CONST命名空間里面:

var CONST = {};
Object.defineProperty(CONST, "A", {
 value: 1,
 writable: false, //設(shè)置屬性只讀
 configurable: true,
 enumerable: true
});
console.log(CONST.A); //1
CONST.A = 2; //在嚴格模式下會拋錯,在非嚴格模式下靜默失敗,修改無效。

但是這樣定義的常量不是絕對的,因為我們依然可以通過修改屬性的數(shù)據(jù)描述符來修改屬性值:

var CONST = {};
Object.defineProperty(CONST, "A", {
  value: 1,
  writable: false,
  configurable: true,
  enumerable: true
});
Object.defineProperty(CONST, "A", {
  value: 2,
  writable: true, //恢復(fù)屬性的可寫狀態(tài)
  configurable: true,
  enumerable: true
})
console.log(CONST.A); //2
CONST.A = 3;
console.log(CONST.A); //3

想要做到真正的常量,還需要將屬性設(shè)置為不可配置:

var CONST = {};
Object.defineProperty(CONST, "A", {
  value: 1,
  writable: false,    //設(shè)置屬性只讀
  configurable: false,  //設(shè)置屬性不可配置
  enumerable: true
});
console.log(CONST.A); //1
CONST.A = 2; //錯誤!屬性只讀
Object.defineProperty(CONST, "A", {
  value: 2,
  writable: true, 
  configurable: true,
  enumerable: true
}); //錯誤!屬性不可配置

但是如果只設(shè)置屬性為不可配置狀態(tài),依然可以對屬性值進行修改:

var CONST = {};
Object.defineProperty(CONST, "A", {
  value: 1,
  writable: true,     //設(shè)置可寫
  configurable: false,  //設(shè)置屬性不可配置
  enumerable: true
});
console.log(CONST.A); //1
CONST.A = 2;
console.log(CONST.A); //2

進而我們可以推斷出,configurable 描述符僅凍結(jié)屬性的描述符,不會對屬性值產(chǎn)生影響,也就是說該描述符會凍結(jié) writable、configurable、enumerable 的狀態(tài),不會對屬性值加以限制:

var CONST = {};
Object.defineProperty(CONST, "A", {
  value: 1,
  writable: false,     //設(shè)置不可寫
  configurable: false,   //設(shè)置屬性不可配置
  enumerable: false    //設(shè)置不可枚舉
});
Object.defineProperty(CONST, "A", {
  value: 2,        //該屬性本身不受 configurable 的影響,但由于屬性不可寫,受 writable 的限制
  writable: true,     //錯誤!屬性不可配置
  configurable: true,   //錯誤!屬性不可配置
  enumerable: true     //錯誤!屬性不可配置
});

但是 configurable 的限制有一個特例,就是 writable 可以由 true 改為 false,不能由 false 改為 true:

var CONST = {};
Object.defineProperty(CONST, "A", {
  value: 1,
  writable: true,     //設(shè)置可寫
  configurable: false,   //設(shè)置屬性不可配置
  enumerable: false    //設(shè)置不可枚舉
});
Object.defineProperty(CONST, "A", {
  value: 2, //該屬性本身不受 configurable 的影響,由于屬性可寫,修改成功
  writable: false, 
  configurable: false, 
  enumerable: false 
});
console.log(CONST.A); //2
CONST.A = 3; //錯誤!屬性只讀

可枚舉描述符用于配置屬性是否可以枚舉,也就是是否會出現(xiàn)在 for ... in ... 語句中:

var CONST = {};
Object.defineProperty(CONST, "A", {
  value: 1,
  writable: false,
  configurable: false,
  enumerable: true //可枚舉
});
Object.defineProperty(CONST, "B", {
  value: 2,
  writable: false,
  configurable: false,
  enumerable: false //不可枚舉
});
for (var key in CONST) {
  console.log(CONST[key]); //1
};

有了以上的基礎(chǔ),我們也就學(xué)會一種定義常量的方法,使用屬性的數(shù)據(jù)描述符,下次我們需要用到常量的時候,就可以定義一個 CONST 命名空間,將常量封裝在該命名空間里面,由于屬性描述符默認為 false,所以我們也可以這樣定義:

var CONST = {};
Object.defineProperty(CONST, "A", {
  value: 1,
  enumerable: true
});
Object.defineProperty(CONST, "B", {
  value: 2,
  enumerable: true
});

以上方法是從屬性的角度的去定義一組常量,不過我們還可以用另外一種方法,從對象的角度去配置一個對象包括它的所有屬性,Object.preventExtensions() 方法可以讓一個對象不可擴展,該對象無法再添加新的屬性,但是可以刪除現(xiàn)有屬性:

var CONST = {};
CONST.A = 1;
CONST.B = 2;
Object.preventExtensions(CONST);
delete CONST.B;
console.log(CONST); //CONST: { A: 1}
CONST.C = 3; //錯誤!對象不可擴展

在該方法的基礎(chǔ)之上,我們可以使用 Object.seal() 來對一個對象密封,該方法會阻止對象擴展,并將該對象的所有屬性設(shè)置為不可配置,但是可寫:

var CONST = {};
CONST.A = 1;
CONST.B = 2;
Object.seal(CONST);
CONST.A = 3;
console.log(CONST.A); //3
Object.defineProperty(CONST, "B", {
  value: 2,
  writable: true,    
  configurable: true, //錯誤!屬性不可配置
  enumerable: false,  //錯誤!屬性不可配置
})  
CONST.C = 3; //錯誤!對象不可擴展

也就是說 Object.seal() 方法相當于幫助我們批量的將屬性的可配置描述符設(shè)置為 false ,所以說在代碼實現(xiàn)層面相當于:

Object.seal = function (obj) {
  Object.preventExtensions(obj);
  for (var key in obj) {
    Object.defineProperty(obj, key, {
      value: obj[key],
      writable: true,
      configurable: false,
      enumerable: true
    })
  };
  return obj;
}

在以上兩個方法基礎(chǔ)上,我們可以 Object.freeze() 來對一個對象進行凍結(jié),實現(xiàn)常量的需求,該方法會阻止對象擴展,并凍結(jié)對象,將其所有屬性設(shè)置為只讀和不可配置:

var CONST = {};
CONST.A = 1;
CONST.B = 2;
Object.freeze(CONST);
CONST.A = 3; //錯誤!屬性只讀
Object.defineProperty(CONST, "B", {
  value: 3,      //錯誤!屬性只讀
  writable: true,   //錯誤!屬性不可配置
  configurable: true, //錯誤!屬性不可配置
  enumerable: false,  //錯誤!屬性不可配置
})  
CONST.C = 3; //錯誤!對象不可擴展

從代碼實現(xiàn)層面上相當于:

Object.freeze = function (obj) {
  Object.preventExtensions(obj);
  for (var key in obj) {
    Object.defineProperty(obj, key, {
      value: obj[key],
      writable: false,
      configurable: false,
      enumerable: true
    })
  };
  return obj;
}

最后我們在來看一下這三個方法的兼容性:

Object.preventExtensions()

Feature Firefox (Gecko) Chrome Internet Explorer Opera Safari
Basic support 4 (2.0) 6 9 未實現(xiàn) 5.1

Object.seal()

Feature Firefox (Gecko) Chrome Internet Explorer Opera Safari
Basic support 4 (2.0) 6 9 未實現(xiàn) 5.1

Object.freeze()

Feature Firefox (Gecko) Chrome Internet Explorer Opera Safari
Basic support 4.0 (2) 6 9 12 5.1

到底還是萬惡的IE,均不兼容IE8

現(xiàn)在,我們也就有了兩種方法在JS中定義常量,第一種方法是從屬性層面上來實現(xiàn),在命名空間上可以繼續(xù)添加多個常量,而第二種方法是從對象層面上來實現(xiàn),對凍結(jié)對象所有屬性以及對象本身:

//第一種方法:屬性層面,對象可擴展
var CONST = {};
Object.defineProperty(CONST, "A", {
  value: 1,
  enumerable: true
});
//第二種方法:對象層面,對象不可擴展
var CONST = {};
CONST.A = 1;
Object.freeze(CONST);

關(guān)于JS常量的問題就講到這里了,許多書籍在介紹JS基礎(chǔ)的時候都會提到JS當中沒有常量,導(dǎo)致許多JS開發(fā)者在一開始就默認了JS是沒有常量的這一說法。從嚴格語法意義上來講,JS確實是沒有常量的,但是我們可以通過對知識的深入和創(chuàng)造力來構(gòu)建我們自己的常量,知識是死的,人是活的,只要我們不停的探索,滿懷著創(chuàng)造力,就會發(fā)現(xiàn)其中不一樣的世界。

以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!

相關(guān)文章

最新評論