ES5新增對象的屬性和方法


隨筆:1、某一技術為什么而生

         2、解決了什么問題

         3、如何使用

     4、給出代碼實例

ES5新增對象的方法

一、凍結對象的freeze()方法(分為深凍結和淺凍結)

var obj1 ={
      a:‘111‘  
}

obj1.a = ‘222‘;
console.log( obj.a ) //output 222 對象的屬性發生了變化

現在我們來看看es5 給我提供一個對象的新方法凍結對象(淺凍結)。

Object.freeze(obj) obj是要凍結的對象,Object.freeze()可以防止對象新增屬性或方法,防止刪除和修改現有的屬性和方法。他其實就是讓對象變成不可變的數據;

 var obj = {
        a:‘111‘
    }
    Object.freeze( obj );

     obj.a = ‘222‘

    console.log( obj.a ); //output 依然是 111 嚴格模式下會報錯  不可修改


   obj.b = ‘222‘;
    console.log( obj.b ) //output undefined 嚴格模式下會報錯 不可新增

delete obj.a;

console.log( obj.a ) // output 依然是111 嚴格模式下會報錯 不可刪除

熟悉js對象(深淺)拷貝的朋友就知道想jQuery extend 的方法第一個參數如果出入的是布爾值true 代表深拷貝,如果忽略直接傳入多個對象就代表淺拷貝。其實對象的凍結也是有深凍結和淺凍結之分的。

var obj = {
   a:{
     achild:‘deep‘  
    }  
}

Object.freeze(obj);

//我現在來改變obj對象a下的achild驗證一下 Object.freeze()是否還靈驗

obj.a.achild = ‘no effect‘;

console.log( obj.a.achild ) //output no effect; 果然是可以改變的。

obj.a.otherchild = ‘otherchild‘;

console.log(  obj.a.otherchild) //output otherchild 也可以新增 

delete obj.a.otherchild ;
console.log(  obj.a.otherchild) // output undefine obj.a.otherchild 不見了真名刪除也是有效的

通過上面的例子我們可以發現Object.freeze(obj) 只可以淺凍結對象 obj.a(淺) obj.a.achild(深)

 那我們想深凍結一個對象怎么辦?我也可以通過Object.freeze()的特性自己創建一個深凍結函數。

function deepFreeze(obj) {


  var propNames = Object.getOwnPropertyNames(obj);

  
  propNames.forEach(function(name) {
    var prop = obj[name];


    if (typeof prop == ‘object‘ && prop !== null)
      deepFreeze(prop);
  });

  return Object.freeze(obj);
}

//現在我們來試驗一下我們的函數
var obj = {
    a:{}
}
deepFreeze(obj);

obj.a.achild = ‘achild‘ 

console.log( obj.a.achild ) //output undefine 現在實現了深凍結一個對象了

二、Object.create() 新增對象的方法

1、Object 對象 (JavaScript)
提供對所有 JavaScript 對象通用的功能。參考網站:https://msdn.microsoft.com/zh-cn/library/kb6te8d3(v=vs.94).aspx
2、Object.create()

概念:Object.create():是E5中提出的一種新的對象創建方式。

語法:Object.create(proto [, propertiesObject ]),第一個參數是要繼承的原型,如果不是一個子函數,可以傳一個null,第二個參數是對象的屬性描述符,這個參數是可選的。

propertiesObject 參數的詳細解釋:(默認都為false)。數據屬性,writable:是否可任意寫;configurable:是否能夠刪除,是否能夠被修改;enumerable:是否能用 for in 枚舉;value:值;訪問屬性:get(): 訪問;set(): 設置

示例如下:

復制代碼
    function Car(desc){
        this.desc = desc;
        this.color = 'red';
    }
    Car.prototype = {
        getInfo:function(){
            return 'A ' + this.color + ' ' + this.desc + '.'; 
        }
    }
    var car = Object.create(Car.prototype);
    car.color = 'blue';
    var info = car.getInfo();
    console.log(info);//A blue undefined.

        var obj = {
        a:function(){
            console.log(100);//100
        },
        b:function(){
            console.log(200)
        },
        c:function(){
            console.log(300)
        }
    }
    var newObj = {};
    newObj = Object.create(obj,{
        t1:{
            value:'yupeng',
            writable:true
        },
        bar: {
            configurable: false,
            get: function() { return bar; },
            set: function(value) { bar=value }
        }
    })

    console.log(newObj.a());//undefined
    console.log(newObj.t1);//yupeng
    newObj.t1 = 'yupeng1'
    console.log(newObj.t1);//yupeng1
    newObj.bar = 201;
    console.log(newObj.bar);//201

3、Object.keys()

Object.keys():返回一個由給定對象的所有可枚舉自身屬性的屬性名組成的數組,數組中屬性名的排列順序和使用for-in循環遍歷該對象時返回的順序一致(兩者的主要區別是 for-in 還會遍歷出一個對象從其原型鏈上繼承到的可枚舉屬性)。

語法:Object.keys(obj)。

參數:obj返回該對象的所有可枚舉自身屬性的屬性名。

復制代碼
    var arr = ['a','b','c'];
    console.log(Object.keys(arr));//["0", "1", "2"]
    // 類數組對象
    var obj = { 0 : "a", 1 : "b", 2 : "c"};
    console.log(Object.keys(obj)); // ["0", "1", "2"]

    // getFoo是個不可枚舉的屬性
    var my_obj = Object.create({}, 
    {
         getFoo : { 
             value : function () { 
                 return this.foo 
             } 
         } 
     });
    my_obj.foo = 1;
    console.log(Object.keys(my_obj)); // ["foo"]
 
         

4、Object.prototype.isPrototypeOf()  用來判斷一個對象實例的原型是否是object

isPrototypeOf:是用來判斷要檢查其原型鏈的對象是否存在於指定對象實例中,是則返回true,否則返回false。

語法:prototype.isPrototypeOf(object)。

參數:prototype,必選。對象原型。 object,必選。另一個對象,將對其原型鏈進行檢查。

示例如下:

復制代碼
function person(name,age){
    this.name = name;
    this.age = age;
}
var person1 = new person('xiaoming',23);
console.log(person.prototype.isPrototypeOf(person1));//true;原型鏈的對象:person,對象實例;person1
 
         

5、Object.getPrototypeOf()

getPrototypeOf:返回對象的原型。

語法:Object.getPrototypeOf(object)

參數:object,必需。引用原型的對象。

返回值:object 參數的原型。原型也是對象。

復制代碼
function person(name,age){
    this.name = name;
    this.age = age;
}
var person1 = new person('xiaoming',23);
var proto = Object.getPrototypeOf(person1);//獲取對象person1的原型
proto.eatFruit = 'apple';    //給原型添加新的屬性
console.log(person1.eatFruit);//apple
var reg = /a/;
var result1 = (Object.getPrototypeOf(reg) === RegExp.prototype);//比較正則表達式對象的原型
console.log(result1 + " ");//true

var err = new Error("an error");
var result2 = (Object.getPrototypeOf(err) === Error.prototype);//比較對象原型
console.log(result2);//true
 
         

6、object.hasOwnProperty()

object.hasOwnProperty(proName):確定某個對象是否具有帶指定名稱的屬性。

語法:object.hasOwnProperty(proName)

參數:object,必需。對象的實例。proName,必需。一個屬性名稱的字符串值

復制代碼
function person(name,age){
    this.name = name;
    this.age = age;
}
person.prototype.singsong = function(songName){
    this.songName = songName;
    console.log('singsong');
}
person.prototype.sayHello = function(){
    console.log('sayHello');
}
var person1 = new person('xiaoming',23);
var person2 = new person('angerbaby',22);
console.log(person1.hasOwnProperty("name"));//true;
console.log(person1.hasOwnProperty("age"));//true;
console.log(person1.hasOwnProperty("singsong"));//false;
console.log(person.prototype.hasOwnProperty("singsong"));//true;
console.log(person.prototype.hasOwnProperty("songName"));//false;  /*只有實例化對象之后,用此對象調用方法,傳參后值不為undefined時,這個屬性才顯示存在*/
 
         

7、Object.getOwnPropertyNames()

Object.getOwnPropertyNames(object):返回對象自己的屬性的名稱。一個對象的自己的屬性是指直接對該對象定義的屬性,而不是從該對象的原型繼承的屬性。對象的屬性包括字段(對象)和函數。

語法:Object.getOwnPropertyNames(object)

參數:object,必需。包含自己的屬性的對象。

返回值:一個數組,其中包含對象自己的屬性的名稱。

復制代碼
function person(name,age,number){
    this.name = name;
    this.age = age;
    this.number = number;
    this.toString = function(){
        return (this.name+","+this.age+","+this.number);
    }
}
var person1 = new person('xiaoming',23,'18615244521');
var propertyArr = Object.getOwnPropertyNames(person1);
console.log(propertyArr);//["name", "age", "number", "toString"]

//下面的示例顯示了使用 person 構造函數構造的 person1 對象中以字母“n”開頭的屬性名。
var names = Object.getOwnPropertyNames(person1).filter(checkkey);//filter(),傳參為一個函數,作用為用這個函數來過濾數組元素
console.log(names);//["name", "number"]
function checkkey(value){
    var firstchar = value.substr(0,1);
    if(firstchar.toLowerCase() == 'n'){
        return true;
    }else{
        return false;
    }
}
//下面的示例創建一個對象,該對象具有三個屬性和一個方法。然后使用 keys 方法獲取該對象的屬性和方法。
var propertyArr1 = Object.keys(person1);
console.log(propertyArr1);//["name", "age", "number", "toString"]
個對象,該對象具有三個屬性和一個方法。然后使用 keys 方法獲取該對象的屬性和方法。
var propertyArr1 = Object.keys(person1);
console.log(propertyArr1);//["name", "age", "number", "toString"]
復制代碼

理解js對象中的可枚舉性(enumerable):

概念:可枚舉性(enumerable)用來控制所描述的屬性,是否將被包括在for...in循環之中。具體來說,如果一個屬性的enumerable為false,下面三個操作不會取到該屬性。

  • for..in循環
  • Object.keys方法
  • JSON.stringify方法
復制代碼
var o = {a:1, b:2};
o.c = 3;
Object.defineProperty(o, 'd', {
  value: 4,
  enumerable: false
});
o.d
// 4

for( var key in o )
 console.log( o[key] ); 
// 1
// 2
// 3

Object.keys(o)  // ["a", "b", "c"]
JSON.stringify(o) // => "{a:1,b:2,c:3}"
//上面代碼中,d屬性的enumerable為false,所以一般的遍歷操作都無法獲取該屬性,使得它有點像“秘密”屬性,但還是可以直接獲取它的值。
//至於for...in循環和Object.keys方法的區別,在於前者包括對象繼承自原型對象的屬性,而后者只包括對象本身的屬性。如果需要獲取對象自身的所有屬性,不管enumerable的值,可以使用Object.getOwnPropertyNames方法
 
         

8、Object.defineProperty()

概念:將屬性添加到對象,或修改現有屬性的特性。

語法:Object.defineProperty(object, propertyname, descriptor)

參數:obj為需要定義的屬性對象;prop為需定義或修改的屬性的名字;descriptor為將被定義或修改的屬性的描述符。
返回值:返回傳入函數的對象,即第一個參數obj

對象里目前存在的屬性描述符有兩種主要形式:數據描述符和存取描述符。數據描述符是一個擁有可寫或不可寫值的屬性。存取描述符是由一對 getter-setter 函數功能來描述的屬性。描述符必須是兩種形式之一;不能同時是兩者。

數據描述符和存取描述符均具有以下可選鍵值:

  • configurable:當且僅當該屬性的 configurable 為 true 時,該屬性才能夠被改變,也能夠被刪除。默認為 false。
  • enumerable:當且僅當該屬性的 enumerable 為 true 時,該屬性才能夠出現在對象的枚舉屬性中。默認為 false。

數據描述符同時具有以下可選鍵值:

  • value:該屬性對應的值。可以是任何有效的 JavaScript 值(數值,對象,函數等)。默認為 undefined。
  • writable:當且僅當該屬性的 writable 為 true 時,該屬性才能被賦值運算符改變。默認為 false。

存取描述符同時具有以下可選鍵值:

  • get:一個給屬性提供 getter 的方法,如果沒有 getter 則為 undefined。該方法返回值被用作屬性值。默認為 undefined。
  • set:一個給屬性提供 setter 的方法,如果沒有 setter 則為 undefined。該方法將接受唯一參數,並將該參數的新值分配給該屬性。默認為 undefined。

記住,這些選項不一定是自身屬性,如果是繼承來的也要考慮。為了確認保留這些默認值,你可能要在這之前凍結 Object.prototype,明確指定所有的選項,或者將__proto__屬性指向null。

復制代碼
// 使用 __proto__
Object.defineProperty(obj, "key", {
  __proto__: null, // 沒有繼承的屬性
  value: "static"  // 沒有 enumerable
                   // 沒有 configurable
                   // 沒有 writable
                   // 作為默認值
});

// 顯式
Object.defineProperty(obj, "key", {
  enumerable: false,
  configurable: false,
  writable: false,
  value: "static"
});

9、Object.defineProperties()

概覽:方法在一個對象上添加或修改一個或者多個自有屬性,並返回該對象。

語法:Object.defineProperties(obj, props)

 參數:obj:將要被添加屬性或修改屬性的對象,props:該對象的一個或多個鍵值對定義了將要為對象添加或修改的屬性的具體配置。

復制代碼
var obj = {};
Object.defineProperties(obj, {
  "property1": {
    value: true,
    writable: true
  },
  "property2": {
    value: "Hello",
    writable: false
  }
  // 等等.
});
alert(obj.property2) //彈出"Hello"







免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM