天天看點

Javascript面向對象-對象屬性詳解一、對象的屬性分類二、屬性的通路方式三、新增/修改屬性四、删除屬性 delete五、檢測對象是否包含某個屬性六、屬性的周遊七、對象字面量與JSON八 、屬性描述符對象

對象的屬性指對象的成員。講解屬性之前介紹一下Object對象,Object對象是所有JavaScript對象的超類(基類)。本文将會使用到Object對象的一些方法。

一、對象的屬性分類

我們先通過講屬性的一些分類,來明确一些概念

1. 屬性可分為自有屬性和繼承屬性

function Person(name,age){
  this.trueName=name;
  this.age=age;
}
Person.prototype.species='human';
Person.prototype.run=function () {
  console.log(this.trueName+' is running');
}
var p1=new Person('Lilyan',18);
console.log(p1);
           

對象中的屬性,根據是否子屬于自身的可分為自有屬性和繼承屬性。

① 自有屬性(own property) :也可叫執行個體屬性;指對象自身的屬性,上述的p1對象中的姓名、年齡等都是自有屬性。

② 繼承屬性(inherited property):也可叫原型屬性;指對象從原型中繼承的屬性。

我們通過在控制台輸出p1來看一下:

Javascript面向對象-對象屬性詳解一、對象的屬性分類二、屬性的通路方式三、新增/修改屬性四、删除屬性 delete五、檢測對象是否包含某個屬性六、屬性的周遊七、對象字面量與JSON八 、屬性描述符對象

2. 可分為屬性和方法

上面的代碼中run的屬性是一個函數,當屬性值是函數的時候,該屬性被稱為方法,可以說方法就是一種特殊的屬性。

3. 可分為公有屬性和私有屬性

關于公有屬性和私有屬性,裡面涉及到了很多名詞,如私有屬性、私有方法、公有屬性、公有方法、特權方法,中間存在一些概念模糊的地方,,我的說法不一定是對的,但我個人就這樣記憶了。

對于構造函數來說,構造函數的執行個體能夠通路的屬性和方法就是公有屬性公有方法,定義在函數内部且沒有通過this聲明的屬性和方法就是私有的屬性和方法。

function Person(name,age) {
  this.name=name; //公有屬性
  var _age=age; //私有屬性,約定私有屬性前加_
  //私有方法
  var checkAge=function(){
    return (_age<18)?_age:'保密';
  };
  //公有方法-特權方法
  this.introduce=function () {
    console.log(this.name+'的年齡:'+checkAge(_age));
  };
}
//公有方法
Person.prototype.species='人類';
Person.prototype.say=function () {
  console.log(this.name+'的年齡:'+this._age);
};
var p=new Person('張三',19);
console.log(p);
p.introduce();
p.say();
           
Javascript面向對象-對象屬性詳解一、對象的屬性分類二、屬性的通路方式三、新增/修改屬性四、删除屬性 delete五、檢測對象是否包含某個屬性六、屬性的周遊七、對象字面量與JSON八 、屬性描述符對象

簡單的說,列印執行個體時,能看到的就是公有屬性公有方法,定義了又看不到的是私有屬性/方法。

私有屬性和私有方法隻能在函數内部使用,所謂特權方法其實也是一種公有方法,它能夠在構造函數外,被其執行個體調用,并且能夠通路構造函數内的私有屬性和方法(如果你了解執行上下文的知識,就很好了解)。

上面的例子中,公有方法say沒有通路到私有屬性,特權方法introduce通路到了私有屬性和私有方法。

4.靜态屬性和靜态方法

靜态屬性和靜态方法一般指不需要構造函數的執行個體化,直接将構造函數作為對象,可以通路的屬性和方法。

function Person(name) {
  this.name=name; //公有屬性
}
Person.species='人類';
Person.say=function () {
  console.log(this.name+'的年齡:'+this._age);
};
console.log(new Person());
console.dir(Person);
           
Javascript面向對象-對象屬性詳解一、對象的屬性分類二、屬性的通路方式三、新增/修改屬性四、删除屬性 delete五、檢測對象是否包含某個屬性六、屬性的周遊七、對象字面量與JSON八 、屬性描述符對象

二、屬性的通路方式

  1. 可用為 ’ . '點通路方式:obj.propertyName,屬性名稱必須為一個字元串,不能為變量。
  2. 可用’ [ ] '中括号方法方式 ,obj[propertyName],此方法通路屬性更加的靈活,可以使用變量來通路屬性

    說明:通路一個不存在的屬性,将傳回undefined。給對象不存在的屬性指派,将會向該對象添加此屬性。

    var p1={
      "true name":"Lily",
    }
    var tn="true name";          
    console.log(p1[tn]);           //Lily
    console.log(p1.gender);   //undefined
    p1.gender='female';		//新增屬性
    console.log(p1.gender);     //female
    p1.gender='male';		//修改屬性值
    console.log(p1.gender);  //male
               

三、新增/修改屬性

上例中,通過給一個不存在的屬性指派的方法實際上實作了新增屬性;

給一個已經存在的屬性重新指派,就實作了修改屬性值。

四、删除屬性 delete

說明:通過delete方法可以删除對象的自有屬性。

function Person(name,age){
  this.trueName=name;
  this.age=age;
}
Person.prototype.species='human';
Person.prototype.run=function () {
  console.log(this.trueName+' is running');
}
var p1=new Person('Lilyan',18);
delete p1.age;
delete p1['species'];  //species是p1的繼承屬性,靜默失敗
           

五、檢測對象是否包含某個屬性

  1. 使用in運算符判斷對象是否包含某個屬性(會檢查自有屬性和繼承屬性);

    文法:屬性 in 對象

    傳回值:如果存在,傳回值為:true;不存在,則為:false。

    console.log('age' in p1);  //true,找到自由屬性age
    console.log('constructor' in p1);   /true,在原型屬性中找到constructor
               
  2. 判斷對象是否擁有一個指定名稱的自有屬性;

    文法:對象.hasOwnProperty(屬性)

    傳回值:如果存在,傳回值為:true;不存在,則為:false。

    console.log(p1.hasOwnProperty('age'));  //true
    console.log(p1.hasOwnProperty('constructor'));  //false,不會檢查原型
               
  3. 判斷指定名稱的屬性是否為可枚舉的自有屬性

    文法:對象.propertyIsEnumerable(屬性)

    前面的例子中,我們為p1增加了一個不可枚舉的屬性x

    console.log(p1.propertyIsEnumerable('age'));  //true
    console.log(p1.propertyIsEnumerable('x'));   //false
               

六、屬性的周遊

這裡用一個構造函數的例子,來講解一下屬性的周遊

function Person(name,age){
    this.trueName=name;
    this.age=age;
  }
  Person.prototype.species='human';
  Person.prototype.run=function () {
    console.log(this.trueName+' is running');
  }
  var p1=new Person('Lilyan',18);

  Object.defineProperty(p1,'x',{
    value:'x',
    enumerable:false
  });
  Object.defineProperty(Person.prototype,'y',{
    value:'y',
    enumerable:false
  });
  console.log(p1);  
           
Javascript面向對象-對象屬性詳解一、對象的屬性分類二、屬性的通路方式三、新增/修改屬性四、删除屬性 delete五、檢測對象是否包含某個屬性六、屬性的周遊七、對象字面量與JSON八 、屬性描述符對象
  • for / in 語句 周遊對象可枚舉的自有屬性和繼承屬性
  • Object對象的4個靜态屬性,Object.keys()、Object.values() 、Object.entries() 、Object.getOwnPropertyNames()可以實作對象的周遊
  1. Object.keys() 傳回一個給定對象==可枚舉的自有屬性(鍵)==組成的數組
  2. Object.values() 傳回一個給定對象可枚舉的自有屬性值組成的數組(ES6新增)
  3. Object.entries() 傳回一個給定對象可枚舉的自有屬性鍵值對組成的數組(ES6新增)
  4. Object.getOwnPropertyNames() 傳回一個給定對象對象不包括Symbol 屬性全部的自有屬性組成的數組。

上面的代碼中,對象p1既有自有屬性又有繼承屬性,其中還有不可枚舉的屬性x和y,下面就來周遊它

var forResult="for/in周遊結果(傳回可枚舉的自有屬性和繼承屬性)";
  for(var key in p1){
    forResult+="\n"+key+":"+p1[key];
  }
  console.log(forResult);
  console.log("Object.getOwnPropertyNames()方法的周遊結果,傳回全部的自有屬性組成的數組(不包括Symbol屬性):");
  console.log(Object.getOwnPropertyNames(p1));
  console.log("Object.keys()方法的周遊結果(傳回可枚舉的自有屬性名組成的數組):");
  console.log(Object.keys(p1));
  console.log("Object.values()方法的周遊結果(傳回可枚舉的自有屬性值組成的數組):");
  console.log(Object.values(p1));
  console.log("Object.entries()方法的周遊結果(傳回可枚舉的自有屬性鍵值對組成的數組):");
  console.log(Object.entries(p1));
           
Javascript面向對象-對象屬性詳解一、對象的屬性分類二、屬性的通路方式三、新增/修改屬性四、删除屬性 delete五、檢測對象是否包含某個屬性六、屬性的周遊七、對象字面量與JSON八 、屬性描述符對象

七、對象字面量與JSON

對象字面量與JSON 字元串形式上看起來很像,JSON 是一種獨立的語言,JSON字元串現在常用于進行前後端的資料互動,JavaScript提供了一個内置對象JSON,可以實作js對象與json字元串的互轉。

JSON 文法規則

  • 資料為 鍵/值 對。
  • 資料由逗号分隔。
  • 大括号儲存對象
  • 方括号儲存數組

JSON.stringify傳回一個字元串,JS對象的可枚舉的自有屬性成為json字元串的鍵,屬性值成為鍵值;

方法名和方法會被過濾掉。

Javascript面向對象-對象屬性詳解一、對象的屬性分類二、屬性的通路方式三、新增/修改屬性四、删除屬性 delete五、檢測對象是否包含某個屬性六、屬性的周遊七、對象字面量與JSON八 、屬性描述符對象

這個對象p1,轉成JSON字元串

PS:JavaScript的JSON對象

八 、屬性描述符對象

在前面我們多次提到可枚舉屬性,不可枚舉屬性,其實能更加微觀的角度去看屬性,還可以有可寫的屬性,不可寫的屬性;可配置的屬性不可配置的屬性等等。

在ES5 中定義了一個名叫“屬性描述符”的對象,用于描述對象屬性的各種特征,屬性的特征分為兩種類型,資料屬性和通路器屬性。

也就是說我們給對象配置一個屬性的同時,還可以配置這個屬性的特征。

使用Object.getOwnPropertyDescriptor() 和Object.getOwnPropertyDescriptors() 可以傳回指定對象屬性的描述

Javascript面向對象-對象屬性詳解一、對象的屬性分類二、屬性的通路方式三、新增/修改屬性四、删除屬性 delete五、檢測對象是否包含某個屬性六、屬性的周遊七、對象字面量與JSON八 、屬性描述符對象
  • 将資料屬性了解為某屬性作為資料表現出的特征,如屬性值是多少、能不能被修改等等;
  • 通路器屬性指某屬性被讀取或修改時表現出的特征。
  • 一個描述符不能同時有(value或writable)和(get或set)關鍵字(将會産生一個異常),如果一個描述符不具有value,writable,get 和 set 任意一個關鍵字,那麼它将被認為是一個資料描述符。
  1. 資料屬性包含的4個屬性:
    資料屬性 預設值 說明
    configrable true 描述屬性是否配置,以及可否删除
    enumerable true 可枚舉性描述屬性是否會出現在for in 或者 Object.keys()的周遊中
    writable true 可寫性,表示能否修改屬性的值。
    value undefined 資料屬性,表示屬性的值
  2. 通路器屬性包含的4個屬性:
    通路器屬性 預設值 說明
    configrable false 描述屬性是否配置,以及可否删除
    enumerable false 描述屬性是否會出現在for in 或者 Object.keys()的周遊中
    get undefined 當通路該屬性時,該方法會被執行,沒有參數傳入,會傳入this對象
    set undefined 該方法将接受唯一參數,并将該參數的新值配置設定給該屬性

使用for/in循環可以周遊對象的可枚舉屬性,下面我用Object對象的defineProperty方法為上面的p1對象增加一個不可枚舉屬性x

Object.defineProperty(p1,'x',{
  value:'x',
  enumerable:false
});
console.log(p1);  //Person {trueName: "Lilyan", age: 18, x: "x"}
console.log(Object.getOwnPropertyDescriptor(p1, 'x'));   //{value: "x", writable: false, enumerable: false, configurable: false}
for(var key in p1) {
  console.log(key);   //不會列印出x,x屬性不可枚舉
}
           

這裡用到了Object對象的兩個方法:

  1. Object.defineProperty(obj, propertyName, propertyDescriptor) :添加/修改對象指定屬性的特性
  2. Object.getOwnPropertyDescriptor(object, propertyName) :傳回對象屬性的描述

    可以跳轉到 JavaScript原生對象-Object對象詳解

繼續閱讀