亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

全面了解JavaScript對象進階

2019-11-20 09:27:06
字體:
來源:轉載
供稿:網友

要了解JavaScript對象,我們可以從對象創建、屬性操作、對象方法這幾個方面入手。概括起來,包括以下幾模塊:  

1.創建對象

1.1 對象直接量

對象直接量是創建對象最簡單的方式,由若干名/值對組成映射表:

var point = {x: 0, y: 0 };

屬性名也沒有什么限制,可以是js的關鍵字或者任意字符串,如果是這兩種情況,屬性需要用雙引號引起來:

var empty = {};va point = {x: 0, y: 0 };var book = {"main title": "Javascript","sub-title": "The definitive Guide","for": "all audience",author: {firstName: "Davide",lastName: "Flanagan"}};

對象直接量創建對象十分簡單,但一般都不會這樣使用。代碼可復用性低,如果想要在其他地方使用該對象并且屬性值不一樣,那這么辦?是不是又得重新創建一份代碼?

1.2 通過new創建對象

通過new創建對象之前,先要創建一個函數,new把這個函數當做構造函數(constructor)。例如通過new創建一個Person對象:

function Person(){//構造函數}var person = new Person();

Javscript語言核心中的原始類型都包含內置構造函數:

var a = new Array();var d = new Date();var r = new RegExp(“js”);

1.3 Object.create()

在了解Object的create方法之前,我們想看看什么是原型。每一個Javascript對象(null除外)都和另一個對象相關聯。“另一個”對象就是我們所說的原型。每一個對象都從原型繼承屬性。

所有通過對象直接量創建的對象都具有同一個原型對象Object.prototype。關鍵字new和構造函數創建的對象原型就是構造函數的prototype屬性的值。通過new Array()創建對象的原型為Array.prototype,通過new Date()創建的對象原型為Date.prototype。原型暫介紹到這里。

Object.create方法包含兩個參數,第一個參數是對象的原型,第二個參數可選,用于描述對象屬性。使用很簡單,只需傳入所需的原型對象即可:

var o1 = Object.create({x: 1, y: 2 }); //原型為Object.prototype

如果想創建一個沒有原型的對象,可通過傳入null作為參數。這樣創建的對象不會繼承任何屬性,也沒有像toString這樣的方法:

var o2 = Object.create(null); //沒有原型

如果想創建一個普通的空對象,直接傳入Object.prototype:

var o3 = Object.create(Object.prototype);

如果是自定義的對象,和創建空對象一樣。直接傳入對象名.prototype:

function Person(){}var o4 = Object.create(Person.prototype);

2.屬性管理

2.1 屬性查詢和設置

對象的屬性可通過點(.)或方括號([])運算符獲取。如果使用點獲取屬性,屬性名必須是簡單的表示符。不能是保留字,比如,o.for或者o.class。

ar author = book.author; //正確var name = author.surname; //正確var title = book[“main title”]; //正確var className = book.class; //錯誤

object[“property”]這種語法看起來更像數組,只是這個數組的元素是通過字符串索引而不是數字索引。這種數組就是我們所說的關聯數組,也稱為散列、映射或字典。Javascript對象都是關聯數組。

既然對象是關聯數組,那么Javascript也為我們提供了屬性的遍歷方式for/in。下面的例子利用for/in計算portfolio的總計值:  

function getvalue(portfolio){  var total = 0.0;  for(stock in portolio){    var shares = portolio[stock];    var price = getquote(stock);    total += shares * price;  }  return total;}

繼承:Javascript對象具有自有屬性(own property),也有一些屬性是從原型對象繼承而來。我們先看看一個實現繼承功能的函數inherit:

function inherit(p){  if (p == null) throw TypeError(); //p是一個對象,大不能是null  if(Object.create){    return Object.create(p); //直接使用Object.create方法  }  var t = typeof p;  if(t !== "object" && t !== "function") throw TypeError();  function f() {};  f.prototype = p; //將其原型屬性設置為p  return new f();}

假設要查詢對象o的屬性x,如果o中不存在x,將會繼續在o的原型對象中查詢屬性x。如果原型對象中也沒有x,但這個原型對象也有原型,那么繼續在這個原型對象的原型上執行查詢,直到找到x或者查詢到一個原型為null的對象為止。

var o = {}; //o從Object.prototype繼承對象屬性o.x = 1; //給o定義x屬性var p = inherit(o); //p繼承o和Object.prototypep.y = 2; //p定義屬性yvar q = inherit(p); //q繼承p、o和Object.prototypeq.z = 3; //給q定義屬性zvar s = q.toString(); //toString繼承自Object.prototypeq.x + q.y // => 3:x和y分別繼承自o和p

2.2 刪除屬性

delete運算符可以刪除對象的屬性:

delete book.author;delete book[“main title”];

delete只能刪除自有屬性,不能刪除繼承屬性。要刪除繼承屬性,必須從定義這個屬性的原型對象上刪除它,而且這會影響到所有的繼承自這個原型的對象。刪除成功會返回true。

ar o = {x: 1};delete o.x; //刪除x,返回truedelete o.x; //x已經不存在了,什么都沒做,返回true。delete o.toString; //什么都沒做,返回true。delete不能刪除可配置型為false的屬性。某些內置對象的屬性是不可配置的,比如通過變量聲明和函數聲明創建的全局對象的屬性:delete Object.prototype //不能刪除,屬性是不可配置的var x = 1;delete this.x; //不能刪除這個屬性function f() {}delete this.f; //不能刪除全局函數

2.3 檢測屬性

判斷某個屬性是否存在于某個對象中,可通過in運算符、hasOwnProperty()和propetyIsEnumerable()方法來檢測。

in運算符:運算符左側是屬性名,右側是對象。如果對象的自有屬性或者繼承屬性包含屬性則返回true:

var o = {x: 1};"x" in o; //true:x是o的屬性"y" in o; //false:y不是o的屬性"toString" in o; //true:o繼承toString屬性

hasOwnProperty()方法:檢測給定的名字是否是對象的自有屬性。對于繼承屬性它將返回false:

var o = {x: 1};o.hasOwnProperty("x"); //true:o有一個自由屬性xo.hasOwnProperty("y"); //false:o中不存在屬性yo.hasOenProperty("toString"); //false:toString是繼承屬性

propertyIsEnumerable()方法:是hasOwnProperty的增強版,只有檢測到自有屬性并且這個屬性是可枚舉行為true時才返回true:

var o = inherit({y: 2});o.x = 1;o.propertyIsEnumerable("x"); //true: o有一個可枚舉屬的自有屬性xo.propertyIsEnumerable("y"); //false:y是繼承來的Object.prototype.propertyIsEnumerable("toString"); //false:不可枚舉

2.4 枚舉屬性

通常使用for/in循環遍歷對象屬性,遍歷的屬性包括自有屬性和繼承屬性。對象繼承的內置方法是不可枚舉的,但在代碼中給對象添加的屬性都是可枚舉的。例如:

var o = {x: 1, y: 2, z: 3}; //三個可枚舉的自有屬性o.propertyIsEnumeable("toString"); //false,不可枚舉for (p in o) //遍歷屬性  console.log(p); //輸出x、y和z,不會輸出toString

有時候我們只想遍歷自有屬性,并且屬性不為函數:

for(p in o){  if(!o.hasOwnProperty(p)) continue;  if(typeof o[p] === "function") continue;}

我們可通過枚舉遍歷功能實現可枚舉屬性的復制:

/** 把p中的可枚舉屬性復制到o中,并返回o* 如果o和p含同名屬性,則覆蓋o中的屬性* 這個函數并不處理getter和setter以及復制屬性*/function extend(o, p){  for(prop in p){ //遍歷p中的所有屬性    o[prop] = p[prop]; //將屬性添加到o中  }  return o;}

ES5定義了兩個用以枚舉屬性名稱的函數。第一個是Object.keys(),返回由對象中可枚舉屬自有屬性名稱組成的數組。第二個枚舉函數是Object.getOwnPropertyNames(),和Object.keys()類似,它返回對象的所有自有屬性,而不僅僅是可枚舉屬性。

3.屬性封裝

3.1 屬性getter和setter 

對象屬性由名字、值和一組特性(attribute)構成的。在ES5中,屬性值可以用一個或兩個方法替代,這兩個方法就是getter和setter。由getter和setter定義的屬性稱做“存取器屬性”,它不同于“數據屬性”,數據屬性只有一個簡單的值。

和數據屬性不同,存取器屬性不具有可寫性(writeable atribute)。如果屬性同時具有getter和setter方法,那么它是一個讀/寫屬性。如果它只有getter方法,那么它是一個只讀屬性,如果它只有setter方法,那么它是一個只寫屬性。讀取只寫屬性總是返回undefined。

存取器屬性定義語法也比較簡單,函數定義沒有使用function關鍵字,而是使用get或set:

var o = {  //普通的數據屬性  data_prop: 1,  //存取器屬性都是成對定義的函數  get accessor_prop(){/* 這里是函數體 */},  set accessor_prop(value){}};

思考下面這個表示2D笛卡爾點坐標的對象。它有兩個普通屬性x和y分別表示x坐標和y坐標,它還有兩個等價的存取器屬性用來表示點的極坐標:

var p = {  //x和y是普通的可讀寫數據屬性  x: 1.0,  y: 1.0,  //r是可讀寫的存取器屬性,它有getter和setter  get r(){return Math.sqrt(this.x * this.x + this.y * this.y); },  set r(newValue){  var oldValue = Math.sqrt(this.x * this.x + this.y * this);  var ratio = newValue / oldValue;  this.x *= ratio;  this.y *= ratio;  },  //theta是只讀存取器屬性,只有getter方法  get theta() { return Math.atan2(this.y, this.x); }};

和數據屬性一樣,存取器屬性是可以繼承的,因此可以將上述代碼中的p對象當做另一個“點”的原型??梢越o性對象定義它的x和y屬性,但r和theta屬性繼承而來:

var q = inherit(p);q.x = 1, q.y = 1;console.log(q.r);cosole.log(q.theta);

3.2 屬性特性

我們可以將存取器屬性的getter和setter方法看成屬性的特性。按照這個邏輯,我們也可把屬性的值同樣看著屬性的特性。因此,可以認為一個屬性包含一個名字和4個特性。

數字屬性的4個特性分別是它的值(value)、可寫性(writeable)、可枚舉性(enumerable)和可配置型(configurable)。

存取器屬性不具有值(value)特性和可寫性,因此包含:讀?。╣et)、寫入(set)、可枚舉性、可配置性。

ES5定義了一個名為“屬性描述符”的對象,這個對象代表那4個特性。數據屬性的描述符對象的屬性有value、writable、enumerable和configurable。存取器屬性的描述符對象則用get屬性和set屬性代替value和writable。其中writable、enumerable、configurable都是布爾值,get屬性和set屬性是函數值。

通過調用Object.getOwnPropertyDescriptor()可以獲取某個對象特定屬性的屬性描述符:

//返回{value: 1, writable: true, enumerable: true, configurable: true}Object.getOwnProeprtyDescriptor({x: 1},"x");//查詢上文中定義的random對象的octet屬性//返回{get: /*func */, set: undefined, enumerable: true, configurable: true}Object.getOwnPropertyDesciptor(random, "octet");//對于繼承屬性和不存在屬性,返回undefinedObject.getOwnPropertyDesciptor({}, "x");Object.getOwnPropertyDesciptor({}, "toString");

從函數名就可以看出,Object.getOwnPropertyDesciptor()只能得到自有屬性的描述符。要想獲得繼承屬性的特性,需要遍歷原型鏈(Object.getPrototypeOf())。

想要設置屬性的特性,或者讓新建屬性具有某些特性,則需要調用Object.defineProperty(),包含三個參數:對象、屬性名、屬性描述符對象:

// 屬性是存在的,但不可枚舉o.x; //=> 1Object.keys(o) //=> []//現在對屬性x做修改,讓它變成只讀Object.defineProperty(o, "x", {writable: true });//視圖更改這個屬性的值o.x = 2; //操作失敗但不報錯,而在嚴格模式中拋出類型錯誤異常//屬性依然是可配置的,因此可通過這種方式對它進行修改:Object.defineProperty(o, "x", {value: 2 });o.x //=> 2//現在將x從數據屬性修改為存取器屬性Object.defineProperty(o, "x", { get: function() {return 0;} });o.x // => 0

 如果要同時修改或創建多個屬性,則需要使用Object.defineProperties()。第一個參數是要修改的對象,第二個參數㐊一個映射表。例如:

var p = Object.defineProperties({}, {  x: { value: 1, writable: true, enumerable: true, configurable: true},  y: { value: 2, writable: true, enumerable: true, configurable: true},  r: {    get: function(){ return Math.sqrt(this.x * this.x + this.y * this.y); },    enumerable: true,    configurable: true  }});

getter和setter的老式API: 在ES5采納之前,大多數Javascript的實現已經可以支持對象直接量語法中get和set寫法。這些實現提供了非標準的老式API用來查詢和設置getter和setter。這些API由四個方法組成,所有對象都擁有這些方法。

__lookupGetter__()和__lookupSetter__()用以返回一個命名屬性的getter和setter方法。

__defineGetter__()和__defineSetter__()用以定義getter和setter,第一個參數是屬性名字,第二個參數是getter和setter方法。  

var o = {};o.__defineGetter__("x", function(){return 0;});o.__defineSetter__("y", function(value){console.log("set value:" + value);});

4.對象的三個屬性

每一個對象都有與之相關的原型(prototype)、類(class)、可擴展性(extensible attribute)。接下來講述這些屬性有什么作用。

4.1 原型屬性

對象的原型屬性是用來繼承屬性的,我們經常把“o的原型屬性”直接叫做“o的原型”。在之前“創建對象”介紹了三種方式創建對象。通過對象直接量創建的對象使用Object.prototype作為它們的原型。通過new創建的對象使用構造函數的prototype屬性作為它們的原型。通過Object.create()創建的對象使用第一個參數作為它們的原型。

在ES5中,可通過Object.getPrototypeOf()查詢對象原型。在ES3中,沒有與之等價的函數,而是使用表達式o.constructor.prototype檢查對象的原型。

要想檢測一個對象是否是另一個對象的原型(或處于原型鏈中),使用isPrototypeOf()方法。例如,可以通過p.isPrototypeOf(o)來檢測p是否是o的原型:

var p = {x: 1}; //定義一個原型對象var o = Object.create(p); //使用這個原型創建一個對象p.isPrototypeOf(o); //=> true,o繼承自pObject.prototype.isPrototypeOf(o) //=> true, p繼承自Object.prototype

Mozilla實現的Javascript對外暴露了一個專門命名為__proto__屬性,用以直接查詢/設置對象原型。但IE和Opera不支持__proto__屬性,所以不建議直接使用__proto__屬性。

4.2 類屬性

對象的類屬性是一個字符串,用以表示對象的類型信息。ES3和ES5都為提供設置這個屬性的方法,只有一種間接方式查詢它。默認的toString()方法返回這種格式的字符串:[object class]。

可通過調用toString()方法,然后提取已返回字符串的第八個到倒數第二個位置之間的字符。但有個麻煩是,很多對象繼承的toString()方法重寫了,為了能夠調用正確的toString()版本,必須間接調用Function.call()方法。下面例子的classof函數可返回任意對象的類:

function classof(o){  if(o === null) return "Null";  if(o === undefined) return "Undefined";  return Object.prototype.toString.call(o).slice(8, -1);}

4.3 可擴展性

對象的可擴展性用以表示是否可以給對象添加新屬性。所有內置對象和自定義對象都是顯式可擴展的。在ES5中,可將對象轉換為不可擴展的。

Object.seal()方法除了能夠將對象設置為不可擴展的,還可以將對象的所有自有屬性都設置為不可配置的。也就是說,不能給對象添加新屬性,而且已有屬性也不能刪除和配置。

Object.isSealed()方法用來檢測對象是否封閉。

Object.freeze()方法將更嚴格的鎖定對象,除了擁有Object.seal()方法的功能外,還可以將自有的所有數據屬性設置為只讀(如果對象的存取器屬性有setter方法,存取器屬性不受影響, 仍可以通過給屬性賦值調用它們)。

Object.isFrozen()用來檢測對象是否凍結。

5.序列化對象

對象序列化是指將對象的狀態轉換為字符串,也可以將字符串還原為對象。ES5提供了內置函數JSON.stringify()和JSON.parse()用來序列化和還原Javascript對象。這些方法都使用JSON作為數據交換格式。例如:

o = {x: 1, y: {z: [false, null, ""]}}; //定義一個測試對象s = JSON.stringify(o); //{"x":1,"y":{"z":[false,null,""]}}p = JSON.parse(s); //p是o的深拷貝

JSON的語法是Javscript語法的子集,它并不能表示Javascript里的所有值。支持對象、數組、字符串、無窮大數字、true、false和null,并且它們可以序列化和還原。NaN、Inifinity和-Inifinity序列化結果都是null。函數、RegExp、Error對象和undefined值不能序列化和還原。

這里在附加說一下對象的方法:

toString()方法:它將返回一個表示調用這個方法的對象值的字符串。很多對象都重寫了toString()方法,比如Array.toString()、Date.toString()以及Function.toStrring()。

toJSON()方法:Object.prototype實際上沒有定義toJSON()方法,但由于需要執行序列化的對象來說,JSON.stringify()方法會調用toJSON()方法。如果在帶序列化的對象中存在這個方法,則調用它。

valueOf()方法:valueOf()方法和toString()方法非常相似,但往往Javascript需要將對象轉換為某種原始值而非字符串的時候才調用它,尤其是轉換為數字的時候。有些內置類自定義了valueOf()方法,比如,Date.valueOf()。

以上這篇全面了解JavaScript對象進階就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美成人一区二区三区电影| 成人免费观看49www在线观看| 91精品久久久久久久久久另类| 欧美视频在线看| 精品国产福利视频| 欧美日韩国产成人在线观看| 欧美午夜www高清视频| 日本不卡视频在线播放| 国产精品999999| 啊v视频在线一区二区三区| 久久久国产视频91| 国产成人+综合亚洲+天堂| 国产欧美一区二区三区在线| 97视频在线免费观看| 国产日韩欧美电影在线观看| 国产精品揄拍一区二区| 亚洲男人天堂2023| 欧美日韩国产麻豆| 欧美性xxxxxxx| 欧美亚洲一级片| 成人观看高清在线观看免费| 国产精品视频专区| 国内精久久久久久久久久人| 欧美午夜精品久久久久久人妖| 久久精品中文字幕| 日韩精品在线观看一区| 日本久久久a级免费| 欧美激情极品视频| 精品美女久久久久久免费| 成人高h视频在线| 久久人人爽人人爽人人片av高请| 精品五月天久久| 日韩av免费一区| 欧美日韩一区二区精品| 青青在线视频一区二区三区| 欧美精品在线网站| 国产欧美 在线欧美| 中文字幕亚洲字幕| 欧美日韩性视频在线| 国产精品xxxxx| 欧美日韩在线观看视频小说| 91在线国产电影| 色妞一区二区三区| 国产日韩欧美电影在线观看| 亲爱的老师9免费观看全集电视剧| 国产精品第2页| 国产美女直播视频一区| 97精品在线视频| 国产精品久久久久久超碰| 国产欧美日韩最新| 成人免费自拍视频| 亚洲第一区在线| 国产精品爽黄69天堂a| 中文国产成人精品久久一| 国产精品电影在线观看| 日韩成人高清在线| 日本精品久久电影| 亚洲经典中文字幕| 国产精品99久久久久久久久| 欧美—级高清免费播放| 欧美国产精品日韩| 伊人久久久久久久久久久| 91精品国产自产在线| 狠狠综合久久av一区二区小说| 91精品久久久久久| 亚洲综合最新在线| 亚洲福利在线播放| 日韩国产高清视频在线| 国产午夜精品理论片a级探花| 2018国产精品视频| 一区二区成人精品| 国产精品久久久久久久美男| 成人免费在线视频网址| 亚洲欧美三级伦理| 亚洲精品美女在线| 国产精品日韩欧美大师| 欧美激情一区二区三级高清视频| 国产精品久久久久久久美男| 亚洲成人网在线观看| 亚洲黄色av网站| 2019中文字幕免费视频| 91香蕉国产在线观看| 亚洲va电影大全| 欧美亚洲视频在线观看| 92看片淫黄大片欧美看国产片| 欧美激情奇米色| 欧美另类极品videosbestfree| 欧美成人在线免费视频| 欧美激情三级免费| 久久九九精品99国产精品| 欧美—级高清免费播放| 欧美精品久久久久久久久久| 色婷婷综合成人| 欧美影院久久久| 久久成人18免费网站| 欧美人在线视频| 欧洲美女7788成人免费视频| 亚洲国产精品国自产拍av秋霞| 九九热精品视频在线播放| 亚洲精品乱码久久久久久按摩观| 亚洲女人被黑人巨大进入al| 亚洲第一色中文字幕| 欧美性色视频在线| 午夜精品一区二区三区在线视| 日本国产欧美一区二区三区| 亚洲区在线播放| 国产成人a亚洲精品| 国产精品69久久| 中文字幕在线看视频国产欧美在线看完整| 91亚洲国产成人精品性色| 欧美性猛交xxxx富婆| 亚洲午夜未满十八勿入免费观看全集| 亚洲欧美自拍一区| 欧美精品免费在线| 成人国产精品免费视频| 欧美亚洲国产日本| 国产日韩av在线| 国产一区二区三区在线看| 国产成人精品在线视频| 欧美性xxxx18| 日韩欧美精品网站| 欧美日韩高清区| 日韩精品在线影院| 久久成年人免费电影| 日韩美女免费观看| 亚洲色图欧美制服丝袜另类第一页| 91po在线观看91精品国产性色| 伊人青青综合网站| 91亚洲国产成人久久精品网站| 亚洲一区二区在线播放| 国产日本欧美在线观看| 久久人人爽亚洲精品天堂| 国产成人综合精品| 成人高h视频在线| 久久精品电影网站| 日韩精品中文字幕在线观看| 91免费国产视频| 国产精品亚洲美女av网站| 亚洲欧洲偷拍精品| 欧美日韩国产精品一区二区三区四区| 国产在线一区二区三区| 4438全国亚洲精品在线观看视频| 精品亚洲一区二区三区四区五区| 懂色av一区二区三区| 欧美日本啪啪无遮挡网站| 中文一区二区视频| 日韩av中文字幕在线| 欧美精品videossex88| 国产欧美日韩精品丝袜高跟鞋| 少妇高潮久久77777| 色琪琪综合男人的天堂aⅴ视频| 久久综合免费视频| 国产成人在线亚洲欧美| 亚洲va久久久噜噜噜| 日韩精品有码在线观看| xxxxx成人.com| 国产精品久久久久久久久久尿| www日韩中文字幕在线看| 国产精品激情av电影在线观看| 国产亚洲视频在线| 欧美丝袜一区二区| 在线看日韩欧美| 国产综合视频在线观看| 日韩精品福利在线|