原 2017/5 JavaScript基礎6--- 對象

1、對象概述

一、定義

對象中包含一系列屬性,這些屬性是無序的。每一個屬性都有一個字符串 key 和 對應的 valuejavascript

var obj = { x :1, y:2};
obj.x //1
obj.y //2

二、對象的 key

訪問對象的屬性時,不管是 數字,仍是字符串都是指向同一個key屬性,使用空對象,或有屬性的對象,做爲key,都會轉化爲字符串 toString而後處理。java

var obj ={};

obj[1] = 1;
obj['1'] =2;
obj; //Object{1:2}

obj[{}] = true;
obj[{x:1}] =true;
obj;// Object{1:2,[object Object]:true}

三、對象結構

1)屬性標籤

對象的屬性能夠動態添加和刪除的,對象的每個屬性,都有不少的屬性標籤、get、set方法。數組

writable 、enumerable、configurable、value、get/setdom

2)對象原型.

建立一個函數 foo,每個函數都有一個 prototype屬性,假設給 foo.prototype.z賦值爲3,這是new一個foo, 這時 obj的原型【[ proto]】就會指向他的構造器的 prototype屬性。這時訪問 obj.x  獲得 1,obj.z 在obj對象上沒有,這時會繼續找他的原型 z=3。函數

function foo(){}
foo.prototype.z =3;
var obj = new foo();

對象中還有【[class]】表示對象屬於哪個種類this

【[extensible]】對象是否容許增長新的屬性spa

2、建立對象、原型鏈

一、字面量 花括號

var obj1 = {x:1 ,y:2};

var obj2 ={
  x:1,
  y:2
  o:{ //對象嵌套
    z:3,
    n:4
  }
};

二、new構造器 /原型鏈

1)原型鏈

function foo(){}
//函數對象默認帶一個 對象屬性 prototype
foo.protptype.z =3

 

2)獲取值

使用new構造器構造新的對象,每個對象後含有一個標籤原型【proto】,原型指向構造器的 ptototype屬性。當煩那個吻對象的屬性時,若是對象自己沒有這個屬性,對象會繼續查找原型,直到null,沒有返回undefined,有獲取到值。prototype

3)賦值

當給對象賦值時不會查找原型鏈,有則修改,沒有則添加。code

當設置 obj.z = undefined  ;再次獲取 obj.z ;// undefined對象

想要訪問原型上的z 則 delete obj .z ; //刪除對象上的屬性,不會影響到原型鏈,而後獲取 obj.z //3。

4)new建立對象

var o =new Object(); //建立一個空對象 ,和{}同樣
var a = new Array();//建立一個空數組,和[] 同樣
var d = new Date();//建立一個表示當前時間Date對象

三、Object .create 建立對象

Object.create()是一個系統內置函數,接收一個參數,通常爲對象,返回一個新建立的對象,而且新建立的對象的原型指向參數。參數{ x : 1} 的原型指向 Object.prototype , obj.x x是從原型鏈繼承的。 

若是傳入一個null,則對象的原型爲 null ,不包含任何方法。

4、屬性操做

  • 讀寫對象屬性
  • 屬性異常
  • 刪除屬性
  • 檢測屬性
  • 美劇屬性

一、普通讀寫操做

對象 . 或者 對象[] 均可以

//建立一個對象
var  obj = { x:1, y:2};
obj.x; //1
obj["y"]; //2 

obj["x"] =3
obj.y = 4

二、動態處理拼接屬性名

var obj = {x1:1, x2:2};
var i = 1, n = 2;

for( ; i<=n; i++){
  console.log(obj['x' + i])
}

輸出:1,2

三、for in遍歷

注意用for in遍歷,有可能遍歷出原型鏈上的屬性。

var p;
for( p in obj){
  console.log(obj[p])
}

四、讀寫異常

var  obj = {x:1}; //建立一個對象
//訪問一個不存在的屬性y
obj.y; //先進行原型鏈查找,若是找到末端仍是找不到,返回undefined
//obj.y爲undefined 再.z報錯
var yz =obj.y.z ;//TypeError:Cannot read property 'z' of undefined
obj.y.z = 2; //TypeError:Cannot set property 'z' of undefined

1)、讀寫前判斷

var  yz;
if(obj.y){ //先判斷是否有y屬性
  yz= obj.y.z
}

//或者 && 判斷 每一個都是true 總體返回true
var yz = obj && obj.y && obj.y.z
//obj存在則繼續向右找,若是爲空直接返回 undefined

五、刪除屬性

1)delete意義 :

當對象上不存在要刪除的屬性時就會返回true,重複刪不會報錯

var person = {age:28,title:'fe'};
delete person.age ;               //true  刪除成功
delete person['title'];           //true  中括號傳入key刪除成功
person.age ;                      //undefined
delete person.age;                //true 重複刪除不存在的屬性不會報錯,返回true

2)不容許刪除的屬性

delete Object.prototype; //false 

//getOwnPropertyDescriptor 第一個參數時要查看對象,第二個參數是要檢測的屬性
var descriptor = Object.getOwnPropertyDescriptor(Object,"property"); //獲取屬性中全部的標籤
descriptor.configurable ;//false 是否可配置:false ,因此delete Object.prototype返回false

3)var 定義的全局變量 局部變量也不能被刪除。

var globalVal = 1; //定義全局變量
delete globalVal; //false 不能夠刪除

(function(){
  var localVal = 1;
  return delete localVal; //不能夠刪除
}());//false

4)全局函數,局部函數也不能夠delete

function fd(){}
delete fd;//false  刪除失敗


(function(){
  function fd(){
    return delete fd;
  }
}());  //false

5)隱式建立全局變量能夠刪除

ohNo = 1; //隱式建立全局變量
window.obNo; //1
delete ohNo;//true 成功刪除 但不推薦

六、屬性操做

1)查看屬性是否存在

var cat = new Object; //構造一個對象
cat.legs = 4;
cat.name = "Kitty"

'legs' in cat ;// true cat中有legs屬性
'abc' in cat ; //false
"toString" in cat; //true, inherited property cat原型是Object.prototype,中toString存在

//表示查找對象上的屬性
cat.hasOwnProperty('legs'); //true
cat.hasOwnProperty('toString'); //false,原型鏈上存在

2)查看屬性是否可枚舉

cat.propertyIsEnumerable('legs'); //true 能夠枚舉
cat.propertyIsEnumerable('toString'); //false

3)設置屬性

Object.defineProperty

Object.defineProperty(cat,'price',{enumerable:false,value:1000});
Object.defineProperty 建立對象標籤都默認爲false
//第一個參數:添加屬性的對象。二、屬性的名字,三、對象,設置標籤

cat.propertyIsEnumerable('price'); //false
cat.haOwnProperty('price');//true

5)操做屬性時判斷屬相是否存在

if( cat && cat.legs){ //存在
 cat.legs*=2; 
}

//或 !=時 null 和undefined是相等的

if(cat.legs != undefined){
 //還能夠寫爲 !==undefined
}

6)屬性枚舉

var  o = { x:1, y:2,z:3}
'toString' in o; //true
o.propertyIsEnumerable('toString'); //false

var key;
for(key in o){ //遍歷屬性,因爲toString是不可枚舉的因此不顯示
  console.log(key) ;//x,y,z
}

利用 Object.create(o) 建立一個 obj對象 原型指向o。此時原型鏈o上的屬性夜默承認枚舉

var obj = Obj.create(o); //原型鏈上的屬性也默承認枚舉
obj.a = 4; //添加一個屬性a 默承認枚舉
var key;
for(key in obj) {
  console.log(key) ; // a,x,y,z
}

只操做本對象上的屬性

var obj = Object.create(o);
obj.a = 4;
var key;
for(key in obj){
  if(obj.hasOwnProperty(key)){ //過濾掉原型鏈的屬性
    console.log(key);//a
  }
}

5、另外一種讀寫方式 get/set方法

一、屬性getter/setter方法

定義 get 、set方法訪問屬性age()

var man = {
  name:'Bosn',
  weibo:'@Bosn',
  get age(){  // get關鍵字  屬性名  函數體 
    return new Date().getFullYear() - 1995; //返回當前日期年份減去生日,算出當前年齡
  },
  set age(val){ 
    console.log('Age can\'t be set to' +val );
 }
}

console.log(man.age);  //22 獲取值時自動調用 get方法
man.age = 100; //Age can't be set to 100 賦值時自動調用set方法
console.log(man.age);  // still 22

二、get/set與原型鏈

當訪問 obj.z,因爲對象上沒有z屬性,會向原型鏈上查找,給z賦值後,發現obj.z仍然爲1。 當obj對象上沒有z屬性,而且發如今原型鏈上有對應的get 或 set 方法時,當嘗試賦值時會走get/set方法,而不會給對象添加新的屬性。

1)原型鏈上的屬性具備get/set方法

用 Object.defineProperty( obj,'z',{}); 來給obj對象添加z屬性,這時 obj.z爲100 ,刪除obj.z ,再次獲取 obj.z 得到原型鏈上 z的get方法 返回1

2)原型鏈上的writable 爲false

定義一個空的對象 o,定義屬性x ,注意經過 Object.defineProperty() 定義的對象,各個標籤的默認是false ---writable = false, configurable = false。在建立一個以o做爲原型的新對象, 修改x的值,不起做用,由於原型鏈上的writable = false,不可改

給obj對象添加屬性,使用Object.defineProperty()

var o {};
Object.defineProperty(o,'x',{value :1});//writable = false, configurable = false
var obj = Object.create(o); //建立一個以o爲原型的新對象
obj.x ;//1

obj.x =200; //修改
obj.x; //still 1 can't change it

//給obj添加屬性x
Object.defineProperty( obj ,'x',{writable:true,condigurable:true, value :100});

obj.x = 100;

obj.x = 500; //修改

obj.x = 500; //修改爲功

6、屬性標籤

一、查看屬性標籤

  1. getOwnPropertyDescriptor 接收兩個參數 一、要判斷的對象 二、字符串類型的屬性名
  2. writable:屬性是否可修改
  3. enumerable:屬性是否可遍歷,在for in中是否可顯示
  4. configurable:屬性標籤是否可再被修改,是否能夠delete
Object.getOwnPropertyDescriptor({pro:true},'pro');
//返回一個對象 Object {value:true,writable:true,enumerable:true,configurable:true}

Object.getOwnPropertyDescriptor({pro:true},'a'); //不存在a屬性 undefined

二、設置屬性標籤

Object.definedProperty 建立屬性,

var person = {} ;//空對象

//傳入對象,屬性名,配置對象{}
Object.definedProperty(person,'name',{
  configurable:false,
  writable:false,
  enumerable:true,
  value:'lalala'

})

person.name;// lalala
person.name = 1; //修改後仍然爲1
delete person.name; //false

繼續添加屬性

Object.definedProperty(person,'type',{
  configurable:true,
  writable:true,
  enumerable:false, //不可枚舉,在for in  中不顯示type屬性
  value:'hahaha'

})
//獲取對象上全部的key
Object.keys(person); //['name']

三、添加多個屬性標籤

Object.defineProperties ( 定義屬性的對象,{ 屬性名:{設置值},屬性名:{...} })

Object.defineProperties(person,{
  title:{ value:'chapter1' , enumerable:true},  //默認值爲false
  salary: {value:10000,enumerable:ttue},

  luck:{ //隨機一個數,通常機率good
    get : function(){ return Math.random()>0.5 ? 'good','bad'}
  },
  
  promote :{ //升一級,工資漲10%
    set: function(level){ this.salary* = 1+level*0.1}
  }

})

Object.getOwnPropertyDescriptor(person,'title');
//獲得一個 Object {value:'chapter1' , enumerable:true, writable:true,configurable:false};

person.salary; //1000
person.promote = 2; //調用set方法 
person.salary ;12000;

只要configurable:true, 就能夠用Object.defineProperties修改值 或標籤值

7、對象標籤、對象序列化

一、對象標籤

對象的每個屬性都是有標籤的,對象也有

[ [proto] ]  、[ [class ] ]、  [[extensible]]

1)原型標籤 _proto_

2)class標籤

表示對象時哪一個類型的

slice(8,-1); //從第8個字符截取直到最後,去掉最後一個字符,toString 會把值轉換爲對象

3)extensible標籤

對象是否可擴展,preventExtension (obj) ;//設置爲禁止擴展,對象不能夠在添加對象,但對象屬性的標籤值不會改變。

Object.seal(obj); //將全部對象的configurable屬性設置爲 false。

Object.freeze(obj); //凍結,writable,configurable 都爲false

二、序列化其餘對象的方法

1)序列化

JSON 屬性要用 " " 引發來

var obj = { x:1,y:true,z:[1,2,3],nullVal:null};
JSON.stringify(obj); // 返回一個字符串 "{"x":1 , "y":true, "z":[1,2,3],"nulVal" :null}"

//若是序列化的值爲undefined,則這個值不會出如今序列化對象中

obj ={ val :undefined, a :NaN , b:Infinity, c:new Date()};
JSON.stringify(obj); // "{"a":null , "b":null, "c":"2017-04-20T14:14:43.910Z"}";
//值爲 notNumber 、Infinity 得到 null 。時間得到UTC時間格式
//反解對象
obj = JSON.parse('{"x" :1 }'); 
obj.x; //1

2)序列化自定義

var obj = {
  x:1,
  y:2,
  o:{
    o1:1,
    o2:2,
    toJSON : function(){ //固定toJSON
      return this.o1 + this. o2 ; //this 指向o
    }
  }

};

JSON。stringify(obj); //"{ "x":1, "y" :2, "o" :3}"

3)其餘對象方法

var obj = {x:1,y:2};
obj.toString(); //"[ object  object]" 返回 object
obj.toString = function(){ return this.x + this.y}; //定義本身的toString方法
"Result" + obj; //"Result3, 理解爲字符串拼接,調用 toString 

+obj; //調用tostring方法,轉化爲數字,相加 得3

//valueOf 嘗試把對象變爲基本類型時調用
obj.valueOf = function () { return this.x + this.y + 100; };
//不管是 轉化爲數字,仍是拼接都會嘗試把對象轉化爲基本類型,先去找valueOf,若是valueOf不存在,或返回對象,

則toString,若是toString也不存在,或者返回對象則報錯
+obj; //103 從 valueOf來的
"Result" + obj ;// "Result103"
相關文章
相關標籤/搜索