JavaScript基礎知識-(對象)

JavaScript中全部的事物都是對象,字符串,數字,數組,日期,等等,JavaScript對象能夠看做是屬性的無序集合,每一個屬性都是一個鍵值對,JavaScript對象除了能夠保持自有屬性,還能夠從一個稱爲原型的對象繼承屬性。對象的方法一般是繼承的屬性,這種「原型式繼承」是JavaScript的核心特徵

1,初識對象

  對象最多見的用法是:建立,設置,查找,刪除,檢測和枚舉它的屬性。屬性包括名字和值。屬性名能夠是包含空字符串在內的任意字符串,屬性值能夠是任意JavaScript的值。除了名字和值意外,每一個屬性還有一些與之相關的值,稱爲:屬性特性,
  (1) 可寫,代表是否能夠設置改屬性的值
  (2) 可枚舉,代表是否能夠經過for/in循環返回該屬性
  (3) 可配置,代表是否能夠三次或者修改該屬性
每一個對象還擁有三個相關的對象特性
  (1) 對象的原型:指向另一個對象,本對象的屬性繼承自它的原型對象
  (2) 對象的類:是一個標識對象類型的字符串
  (3) 對象的擴展標記:指明瞭是否能夠向該對象添加新的屬性數組

2,對象的建立

(1) 對象直接量
    var obj = {x:1,b:2}  
(2) 經過new建立  
    var obj = new Array()  
    var date = new Date()  
(3) 經過Object.create()建立  
    var obj = Object.create()
複製代碼

3,瞭解原型

  每個JavaScript對象(null除外)都和另外一個對象相關聯,‘另外一個’對象就是咱們熟知的原型,每個對象都從原型繼承屬性。用對象直接量建立的對象都具備同一個原型對象,經過Object.prototype得到對原型對象的引用。經過new建立的對象,原型就是構造函數的prototype屬性的值,好比:Array.prototype,Date.prototype。沒有原型對象的:Object.prototype就只其中之一。普通對象都具備原型,Array.prototype的屬性繼承自:Object.prototye, 所以:new Date()建立的Date對象的屬性同時繼承Date.prototype,和Object.prototye,這就是原型鏈bash

4,屬性的查詢和設置

  能夠經過點(.)或者方括號([]),好比:obj.a 或者 obj['a']均可以得到屬性值,   ECMAScript 3中,點運算符後的標識符不能使用保留字,ES5放寬了限制,常見的兩種例外狀況:對象屬性名是個關鍵字,那麼只有用中括號去訪問,若是屬性名是個不肯定參數,那麼也只能用中括號去訪問函數

5,刪除屬性

  delete運算符只能刪除自由屬性,不能刪除繼承屬性,也不能刪除那些不可配置的屬性,返回值是true或者falseui

6,檢測屬性

  判斷某個屬性是否存在於某個對象中,能夠經過in運算符,hasOwnProperty() 和proertyIsEnumerable()方法
  (1)in運算符 (檢測自有屬性和繼承屬性)this

var obj = { x: 1, y: 2}
 "x" in obj
 // 左側是屬性名,右側是對象,若是對象的自有屬性或繼承屬性含有這個屬性,返回true
複製代碼

  (2)hasOwnProperty()函數(檢測自有屬性)spa

var obj = { x:1, y:2}  
    obj.hasOwnProperty('x')
// hasOwnProperty()用來檢測是不是對象的自有屬性,不會查找原型屬性的
複製代碼

  (3)propertyIsEnumerable()是hasOwnProperty()的加強版,只有檢測到自有屬性且這個屬性的可枚舉性爲true的時候,才返回trueprototype

7,枚舉屬性

  枚舉屬性: for-in 循環。
  for-in循環能夠在循環體中遍歷對象中全部可枚舉的屬性,包括自有屬性和繼承屬性,把屬性名稱賦值給循環變量,切記:對象繼承的內置方法不可枚舉code

var obj = { x:1, y:2, z:3};                // 三個都是可枚舉的屬性
    obj.propertyIsEnumerabel('toString')  // =>false 不可枚舉
    for(item in obj) {
        console.log(item)                // 輸出:x,y,z,沒有toString
    }
// 切記: 對象繼承的內置方法是不可枚舉的
for(item in obj){
    if(!obj.hasOwnProperty('item')
    continue;   // 跳過繼承的屬性
}
for(item in obj) {
    if(typeof obj[item] === 'function') {
        continue;  // 跳過方法
    }
}
複製代碼

  除了for-in循環以外,還有兩個方法
  (1)Object.keys(), 返回一個數組,這個數組有對象中可枚舉的自有屬性的名稱組成
  (2)Object.getOwnPropertyNames() 返回數組,只是它返回對象的全部自有屬性的名稱,而不單單是可枚舉的屬性,還包括不可枚舉屬性對象

8,屬性getter和setter

  對象屬性是由名字,值,和一組特性構成。屬性值能夠用一個或者兩個方法替代,這兩個方法就是getter,和setter,簡稱「存取器屬性」。
  數據屬性只有一個簡單的值。
  和數據屬性同樣,存取器屬性也是能夠繼承的繼承

9,屬性的特性

  能夠認爲一個屬性包含:一個名字和4個特性。

  • 數據屬性4個特性:值(value),可寫性(writable),可枚舉性,可配置性
  • 存取器屬性:取(get),寫入(set),可枚舉性,可配置性
    爲了實現屬性特性的查詢和設置操做,ES5定義了‘屬性描述符’對象
    數據屬性的描述符對象屬性有:value, writable, enumerable, configurable
    存取器屬性的描述符對象屬性:get, set, enumerable, configurable
    經過調用Object.getOwnPropertyDescriptor() 可獲取特定屬性的屬性描述符
var obj = { x:1, y:2, z:3};
console.log(Object.getOwnPropertyDescriptor(obj, 'x'))
// 返回: {value:1, writable:true, enumerable:true, configurable: true}
複製代碼

 存取器屬性:{set: undefined,get:function,enumerable:true,configurable:true}  Object.getOwnPropertyDescriptor()只能獲得自有屬性
 要想得到繼承屬性的特性,須要遍歷原型鏈:用Object.getPrototypeOf()
 想要設置屬性特性,或者新建屬性具備什麼特性:用Object.definePeoperty()

var obj = {};
    Object.defineProperty(obj, 'x',{
    	value: 'zlm',
    	writable: true,     // 可編輯
    	enumerable: false, //不可枚舉
    	configurable: true
    })
    console.log(obj.x) // => zlm 屬性是存在的
    console.log(Object.keys(obj)) // =>[] 不可枚舉,因此輸出空數組 []
    Object.defineProperty(obj,'x', {
    	writable:false
    })
    obj.x = 222;
    console.log(obj.x)  // =>zlm,值沒有改變,由於是不可寫入
    Object.defineProperty(obj, 'x',{
    	value: 444
    })
    console.log(obj.x) // =>444 屬性依然可配置,因此值能夠修改
    Object.defineProperty(obj, 'x', {
    	get: function() {
    		return 555;
    	}
    })
    console.log(obj.x) // =>555 將x從數據屬性修改成存取器屬性
複製代碼

注意:Object.defineProperty()不能修改繼承屬性,同時要修改或建立多個屬性,使用:Object.defineProperties()

// 第一個參數是:要修改的對象
// 第二個參數是:一個映射表,包含新建或者修改的屬性名稱和屬性描述符
  var p = Object.defineProperties({},{
  	x: {value:1,writable:true,enumerable:true,configurable:true},
  	y: {value:2,writable:true,enumerable:true,configurable:true},
  	z: {
  		get: function() { return this.x * this.x + this.y *this.y },
  		enumerable:true,
  		configurable: true
  	}
  })
  console.log(p.x , p.y , p.z)
複製代碼

屬性特性的複製

Object.defineProperty(Object.prototype, 'extentd', {
  	writable:true,
  	enumerable: false,
  	configurable:true,
  	value: function(o) {
  	   //遍歷o對象中全部的自有屬性
  		var names = Object.getOwnPropertyNames(o)  
  		for(var i =0; i< names.length; i++) {
  			if(names[i] in this) continue
  			// 獲取o中的屬性的描述符
  			var desc = Object.getOwnPropertyDescriptor(names[i])
  			// 給當前對象建立一樣的屬性描述符
  			Object.defineProperty(this,names[i],desc)
  		}
  	}
  })
複製代碼

10,對象的是三個屬性

  • 原型
  • 可擴張性
    (1)原型屬性是在實例對象建立之初就設置好的,
    經過對象直接量建立的對象,原型是:Object.prototype()
    經過new建立的對象:原型:構成函數.prototype
    經過Object.create()建立的對象,原型是:第一個參數
    想要檢測一個對象是不是另外一個對象的原型,經過:isPrototypeOf()方法
    例如:p.isPrototypeOf(o) 檢測p是不是o的原型
    (2)類的屬性
    獲取對象的類方法:調用對象的toString()方法,提取第8個和倒數第二位的字符
function classof(o) {
	if(o === null) return "NULL";
	if(p === undefined) return "Undefined";
	return Object.prototype.toString.call(o).slice(8, -1)
	}
	classof({})
	classof(null)
	classof("")
	classof(false)
	classof([])
	classof(new Date())
	classof(/,/)
	classof(window)
複製代碼

(3)對象的可擴展性表示是否能夠給對象添加新屬性,全部內置對象和自定義對象都是顯示可擴展的
ES5提供了能夠用來查詢和設置對象的可擴展性函數:Object.esExtensible()
設置對象爲不可擴展,封閉的:Object.preventExtensions(),Object.seal()
檢測對象是否封閉:Object.isSealed()
更嚴格的鎖定對象,凍結:Object.freeze()
檢測對象是否凍結:Object.isFrozen()

11,對象的序列化

  對象的序列化是指:將對象的狀態轉換爲字符串,也可將字符串還原爲對象   ES5提供了內置函數:JSON.stringify() 用來序列化,JSON.parse()還原對象

相關文章
相關標籤/搜索