摘要:通過對返回字符串切片第位到倒數第位即可獲得對象的類型。測試對象是的深拷貝是的子集,不能表示中所有值。序列化結果是,對象序列化結果是日期字符串不能表示函數對象和只能序列化對象自有的可枚舉屬性。
對象
對象是JavaScript的基本數據類型:屬性的無序集合。每個屬性key: value和屬性描述符descripter組成。
屬性名key:字符串或合法的變量標識符;
屬性值value:可以是任意JavaScript值(number、string、boolean、null、undefined和數組、對象).
value可以是getter和setter。
屬性描述符descripter:每個屬性的三個相關特性writable、enumerable、configurable,其值都是布爾類型,默認都為true
1 創建對象創建對象有三種方法:對象字面量{a: 1},new Constructor()、Object.create()
1.1 對象字面量var book = { "main title": "JavaScript", //有空格或其他非標識符、關鍵字,必須使用雙引號 "sub-title": "The Definitive Guide", "for": "all audiences", author: { firstname: "David", lastname: "Flanagan" } }1.2 new操作符調用構造函數
可以使用new操作符調用一個構造器函數Constructor()創建一個對象。
var o = new String(); var d = new Date();1.3 Object.create()方法
原型:每個JS對象都有一個與之相關聯的原型對象prototype,對象其原型對象上繼承屬性。(當前對象中的__proto__屬性是其原型對象的鏈接)
所有通過字面量創建的對象的原型都是Object.prototype,一個字面量對象{}相當于調用new Object()。
Object.prototype的原型是null,所以null是原型的出口。
Object.create()是一個靜態函數(不是提供給對象調用的方法),用于創建對象:
第一個參數:原型對象,創建的新對象以該參數為原型;
第二個參數:可選,用于對對象屬性的描述
創建一個沒有原型的對象:Object.create(null);
創建一個普通空對象({}或new Object()):Object.create(Object.prototype);
2 對象三個特殊屬性每個對象都有與之相關的3個屬性:原型prototype、類屬性calss attribute、可擴展性extensible attribute
2.1 原型每個JS對象都與另一個原型對象(prototype),利用原型可以實現繼承。
字面量的原型是:Object.prototype
new操作符創建的對象其原型:構造器函數的原型(prototype屬性)
Object.create()創建的對象,其原型:第一個參數
查詢對象的原型ES5中定義了Object.getPrototypeOf()函數,來查詢對象的原型
利用new創建的對象會繼承constructor屬性,指向創建該對的構造器函數,所有該對象的原型是:obj.constructor.prototype
字面量{}的constructor屬性指向Object()
使用isPrototypeOf()方法查看一個對象是否為另一個對象的原型(或處于原型鏈中)
Array.prototype.isPrototypeOf([]); // ==> true2.2 類屬性
對象的類屬性class attribute是一個字符串,用來表示對象的信息。ES3與ES5均為提供設置類屬性的API,只能通過繼承自Object.prototype的toString()方法來簡潔查詢。
{}.toString(); // ==> "[object Object]"
通過對返回字符串切片:第8位到倒數第2位即可獲得對象的類型。但是許多對象重寫了toString()方法,需要間接調用Function的call()方法
function classof(o) { if(o === null) {return "Null";} if(o === undefined) {return "Undefined"} return Object.prototype.toString.call(o).slice(8, -1); }
classof()方法可以返回傳遞給它的任意對象的類型,參數為number、string、boolean時,使用包裝類型將其轉化為對象,再進行操作。
classof(null); // ==> "Null" classof(2); // ==> "Number" classof(false); // ==> "Boolean" classof(new Date()); // ==> "Date" classof(""); // ==> "String" classof({}); // ==> "Object" classof([]); // ==> "Array" classof(/./); // ==> "RegExp" classof(window); // ==> "Window",宿主對象 function F() {}; //自定義一個構造器函數 classof(new F()); // ==> "Object"2.3 可擴展性extensible attribute
對象的課擴展性用來描述對象是否可以添加新的屬性。所有的內置對象和自定義對象都是可擴展的,除非將其轉化為不可擴展
Object.esExtensible()函數判斷傳入對象是否可以擴展;
Object.preventExensible()函數將傳入的對象設置為不可擴展,并且過程不可逆;只影響對象本身的可擴展性
Object.seal()函數將對象設置為不可擴展,屬性描述符configurable設置為false(不能添加新屬性,已有的屬性不能刪除或配置,但是對于writable: true時,可以修改屬性的值);過程不可逆
Object.isSealed()函數判斷一個對象是否封閉
Object.freeze()函數將對象設置為不可擴展,屬性描述符configurable: false;,writable: false;只讀。value為accessor property含有setter函數,不受影響
3 組成對象的屬性每個對象是無需的屬性集合,屬性名可以是合法的變量標識符或字符串;變量值可以是任意JavaScript值;屬性由描述符descripter來控制特性;
3.1 屬性的查詢與設置屬性可以通過.和[]來訪問:
使用.訪問時,其右側必須是屬性名稱命名的簡單標識符
使用[]訪問時,括號內必須是計算結果為字符串的表達式,字符串是屬性的名字。變量名為關鍵字、含有空格或屬性名是變量時,必須使用[]
var author = book.author; var name = author.surname; var title = book["main title"];
屬性的設置:與訪問相似,將其放在賦值表達式的左側
book.edtion = 6; book["main title"] = "ECMAScript";繼承與錯誤
在查詢一個對象是否存在時,先查看自身屬性,如果沒有;通過原型鏈逐層向上查找,直到原型鏈頂端null為止。
如果自身屬性與原型鏈中均為找到,屬性訪問返回undefined,不報錯
如果查詢不存在對象的屬性,會報錯
為null和undefined設置屬性會報錯
3.2 屬性刪除使用delete操作符,可以刪除對象的屬性(其描述符中configurable為true),并且只能刪除自有屬性,不能刪除繼承屬性
3.3 屬性檢測判斷某個屬性是否在某個對象中,JS有三種方法:in、hasOwnProperty()、propertyIsEnumerable()
in:如果對象自身屬性或繼承屬性中包含該屬性,返回true;
hasOwnProperty():只有對象自身屬性包含該屬性時,才返回true
propertyIsEnumerable():只有對象自身屬性包含該屬性,并且該屬性是可以枚舉(描述符中enumerable: true;)
var o = {a : 1}; "a" in o; // ==> true o.hasOwnProperty("a"); // ==> true o.propertyIsEnumerable("a"); // ==> true3.4 枚舉屬性
使用for-in循環可以遍歷對象中所有可枚舉的屬性(包括自身屬性與繼承屬性),把屬性名賦值給循環變量。ES5定義了Object.keys()和Object.getOwnPropertyNames()兩個函數用來枚舉屬性名稱。
Object.keys():返回對象中可枚舉的自有屬性名組成的數組
Object.getOwnPropertyNames():返回對象所有的自有屬性名組成的數組,包括不可枚舉的屬性
對象繼承的內置方法都是不可枚舉的,給對象中增加的屬性都可以枚舉(除非設置其enumerable: false)
有許多使用工具庫為Object.prototype增加新的屬性,這些屬性可以被所有對象繼承使用,但是在ES5之前,不能將其設置為不可枚舉,所以在for-in循環時會被枚舉出來。
//過濾繼承的屬性 for(p in o) { if(!o.hasOwnProperty(p)) {continue;} } //跳過方法 for(p in o) { if(typeof p === "function") {continue;} }
操作對象屬性的工具函數:
/** * 枚舉屬性的工具函數 * 將對象p中可枚舉的屬性復制到對象o中,返回對象o; * 如果p和o含有同名的屬性,則覆蓋o中的屬性 * 不處理getter和setter以及復制屬性 */ function extend(o, p) { for(let prop in p) { o[prop] = p[prop]; } return o; } /** * 將對象p中可枚舉的屬性復制到對象o中,返回對象o; * 如果o和p有同名屬性,不影響o中的屬性 * 不處理getter和setter以及復制屬性 */ function merge(o, p) { for(let prop in p) { if(o.hasOwnProperty(prop)) { continue; } o[prop] = p[prop]; } return o; } /** * 如果o中的屬性在p中沒有同名屬性,從o中刪除這個屬性,并返回o */ function restrict(o, p) { for(let prop in o) { if(!(prop in p)) { delete o[prop]; } } return o; } /** * 如果o中的屬性在p中存在同名屬性,從o中刪除這個屬性,并返回o */ function substrict(o, p) { for(let prop in o) { if(prop in p) { delete o[prop]; } } return o; } /** * 返回一個數組,包含o中可枚舉的自有屬性的名字 */ function keys(o) { //o必須是對象 if(typeof o !== "object") { throw TypeError(); } var result = []; for(let prop in o) { if(o.hasOwnProperty(prop)) { result.push(prop); } } return result; }3.5 屬性setter和getter
屬性的組成:key、value、descripter。在ES5中,value可以用一個或兩個方法替代(getter和setter方法)
所有JavaScript的value叫做數據屬性data property
getter和setter定義的屬性叫做存取器屬性:accessor property
不同于data property,accessor property的讀寫屬性由getter和setter決定。
如果屬性同時有getter和setter,它是一個可讀寫的屬性;
如果屬性只有getter,它是一個只讀的屬性;
如果屬性只有setter,它是一個只寫的屬性;讀取只寫屬性總是返回undefined
getter和setter定義var o = { data_prop: value; //普通數據屬性 //存取器屬性是成對定義的函數,函數名是該屬性名,沒有冒號分隔函數體以屬性名 get accessor_prop() {...}, set accessor_prop(value) {...} }
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.y); var ratio = newvalue / oldvalue; this.x *= ratio; this.y *= ratio; }, //theta是只讀存取器屬性,只有getter方法 get theta() {return Math.atan2(this.y, this.x)} };
函數體內的this指向表示這個點的對象
3.6 屬性的描述符descripter屬性除key、value,還有一組用于描述其特性的descripter,其中有writable、enumerable和configurable三個屬性,其值都為布爾類型,默認為true
假設將setter和getter看做descripter,同理將屬性的value也看做descripter
data property的四個特性:value、writable、enumerable、configurable
accessory property的四個特性:getter、setter、enumerable、configurable
ES5提供操作descripter的API:
調用Object.getOwnPropertyDescripter()函數,獲取某個對象中特定自有屬性的descirpter
調用Object.getPrototypeOf()函數可以獲取繼承屬性的descirpter
調用Object.defineProperty()函數可以設置屬性的特性,或者新建屬性,使其具有某種特性
//返回{ value: 1, writable: true, enumerable: true, configurable: true } Object.getOwnPropertyDescriptor({a: 1}, "a"); //繼承屬性和不存在的屬性,返回undefined Object.getOwnPropertyDescriptor({}); Object.getOwnPropertyDescriptor({}, "toString");
var o = {}; //創建空對象 //添加一個不可枚舉的屬性,其值為1 Object.defineProperty(o, "x", {value: 1, writable: true, enumerable: false, configurable: true}); o.x; //屬性存在,但不可枚舉, ==>1 Object.keys(o); // ==> [] //對x屬性進行修改,使其變為只讀 Object.defineProperty(o, "x", {writable: false}); o.x = 2; //操作失敗,但不報錯;在嚴格模式下拋出類型錯誤 o.x; // ==> 1 //屬性的值可以配置 Object.defineProperty(o, "x", {value: 2}); o.x; // ==> 2 //將x從數據屬性修改為存取器屬性 Object.defineProperty(o, "x", {get function() {return 0;}}); o.x; //==> 04 序列化對象
序列化對象指將對象的狀態轉化為字符串,同時可以將JSON字符串轉化為對象。ES5內置JSON對象的JSON.stringgify()和JSON.parse()可以完成序列化和解析。
var o = {x: 1, y: {z: [false, null, ""]}}; //測試對象 var s =JSON.stringify(o); // "{"x":1,"y":{"z":[false,null,""]}}" var p = JSON.parse(s); //p是s的深拷貝
JSON是JavaScript的子集,不能表示JavaScript中所有值。
可以表示:object、Array、string、number、boolean、null,可以序列化與還原。infinity、NaN序列化結果是null,Date對象序列化結果是日期字符串
不能表示:函數、RegExp、Error對象和undefined
JSON.stringify()只能序列化對象自有的可枚舉屬性。
5 Object.prototype對象的方法hasOwnProperty():檢測該屬性是否為對象自有屬性
propertyIsEnumerable():檢測該屬性是否是對象自有,并且可枚舉的屬性
isPrototypeOf:檢測某對象是否為另一個對象的原型
toString():無參數,返回調用該方法對象值的字符串,由于功能有限,某些對象重寫了該方法:Array.toString()、Date.toString()、Function.toString()
toLoaclString():Object中的toLoaclString()只是調用toString(),只有Date和Number類對toLoaclString()定制,可以對數字、日期和時間進行本地化處理
6 總結JS中對象是屬性的無序集合,每個對象有三個相關特性:原型prototype、類屬性class property、可擴展性extensible
對象的創建三種方法:對象字面量、new調用構造函數和Object.create()
每個屬性由三個部分組成:key、value和descripter
key只能是字符串或者值為字符串的變量標識符
value可以是任意JavaScript值(數據屬性data property);可以是一個或兩個方法,getter和setter(控制區屬性accessor property)
descripter:writable、enumerable、configurable,其值都是布爾類型,默認都為true。可以使用Object.defineProperty()操作描述符特性。
writable指該屬性是否可以寫入數據;enumerable指該屬性是否可以枚舉,(使用for-in循環可以列出,ES5提供Object.keys()和Object.getOwnPropertyNames());configurable指該屬性是否可以用delete操作符刪除和配置。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/81811.html
摘要:對象數組初始化表達式,闖關記之上文檔對象模型是針對和文檔的一個。闖關記之數組數組是值的有序集合。數組是動態的,根闖關記之語法的語法大量借鑒了及其他類語言如和的語法。 《JavaScript 闖關記》之 DOM(下) Element 類型 除了 Document 類型之外,Element 類型就要算是 Web 編程中最常用的類型了。Element 類型用于表現 XML 或 HTML 元素...
摘要:理解的函數基礎要搞好深入淺出原型使用原型模型,雖然這經常被當作缺點提及,但是只要善于運用,其實基于原型的繼承模型比傳統的類繼承還要強大。中文指南基本操作指南二繼續熟悉的幾對方法,包括,,。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。 怎樣使用 this 因為本人屬于偽前端,因此文中只看懂了 8 成左右,希望能夠給大家帶來幫助....(據說是阿里的前端妹子寫的) this 的值到底...
摘要:對象在中,除了數字字符串布爾值這幾個簡單類型外,其他的都是對象。那么在函數對象中,這兩個屬性的有什么區別呢表示該函數對象的原型表示使用來執行該函數時這種函數一般成為構造函數,后面會講解,新創建的對象的原型。這時的函數通常稱為構造函數。。 本文原發于我的個人博客,經多次修改后發到sf上。本文仍在不斷修改中,最新版請訪問個人博客。 最近工作一直在用nodejs做開發,有了nodejs,...
摘要:然后將構造函數的原型設為,便實現了對象繼承。首先,我們定義一個構造函數,并在其中定義一個局部變量。這里的是局部變量,其作用域仍然存在是閉包現象,而非對象屬性。 Javascript是動態的,弱類型的,解釋執行的程序設計語言。 Javascript極其靈活,支持多種程序設計范式:面向對象、指令式、函數式。JavaSCript最初被用于瀏覽器腳本,現在已經是所有主流瀏覽器的默認腳本語言。瀏...
摘要:可嵌入動態文本于頁面,對瀏覽器事件作出響應,讀寫元素,控制等。年月,發布了一款面向普通用戶的新一代的瀏覽器版,市場份額一舉超過。網景將這門語言作為標準提交給了歐洲計算機制造協會。線程和的并發執行都是線程安全的。后面會詳細講解對象類型的轉換。 本文由云+社區發表作者:殷源,專注移動客戶端開發,微軟Imagine Cup中國區特等獎獲得者 JavaScript越來越多地出現在我們客戶端開...
摘要:在中,并沒有對抽象類和接口的支持。例如,當對象需要對象的能力時,可以有選擇地把對象的構造器的原型指向對象,從而達到繼承的效果。本節內容為設計模式與開發實踐第一章筆記。 動態類型語言 編程語言按數據類型大體可以分為兩類:靜態類型語言與動態類型語言。 靜態類型語言在編譯時已確定變量類型,動態類型語言的變量類型要到程序運行時,待變量被賦值后,才具有某種類型。 而JavaScript是一門典型...
閱讀 846·2021-10-25 09:48
閱讀 617·2021-08-23 09:45
閱讀 2509·2019-08-30 15:53
閱讀 1765·2019-08-30 12:45
閱讀 608·2019-08-29 17:21
閱讀 3423·2019-08-27 10:56
閱讀 2557·2019-08-26 13:48
閱讀 704·2019-08-26 12:24