摘要:所以對象也可說是一組名字屬性的組合。如果想要訪問,就用專用的方法,包含兩個參數對象名稱,屬性名稱,返回一個對象包含具體的特性。
基于《javascript 面向對象精要》整理下思路:
ECMA5 對象的定義是無序屬性的集合,屬性可以是基本值,對象(包含函數),屬性都有一個名字,名字可以是標識符或者是字符串,映射到屬性。所以對象也可說是一組名字/屬性的組合。
有兩種方式創建對象:構造函數,字面量;
//構造函數,先定義,在賦值 var obj1 = new Object(); obj1.name = "obama"; //字面量,直接賦值 var obj2 = { name : "bush" }
讀取屬性也有兩種方式
obj1.name //常用的是使用 . 點號直接讀取屬性 obj1["name"] //使用中括號里面是屬性的字符串(有引號)也可以讀取 //如果屬性包含空格或者其他的非合法標識符就只能使用中括號,
屬性有兩種:
1,數據屬性 named data property
2,訪問器屬性 named accessor property
兩者的區別,先看數據屬性的例子
var obj = { name : "obama" } obj.name; consle.log(obj.name) //obama //正常情況下,直接訪問obj.name 不會輸出任何結果,只是引擎訪問這個屬性,等待下一步的操 //作,如果有下一步操作,就把這屬性的值返回出來,提供使用如:console.log()。
也就是說,數據屬性包含屬性的具體的值,我們可以訪問,訪問器屬性則沒有,只供引擎使用,
那么如何描述這兩個屬性呢,那就是特性,attribute(描述對象屬性的屬性),正常情況下,不可訪問,在內部用[[ ]]包裹。如果想要訪問,就用專用的方法,
Object.getOwnPropertyDescriptor(object,property)包含兩個參數(對象名稱,屬性名稱),返回一個對象包含具體的特性。
var obj = { name : "obama" } var properties = Object.getOwnPropertyDescriptor(obj,"name"); console.dir(properties);
可以看到有四個屬性,這些就是屬性的數據屬性,我們可以訪問的到的,也是可以修改的,使用兩個特殊的方法
Object.defineProperty(); 定義單個對象的屬性
Object.defineProperties(); 定義多個對象的屬性
記住使用以上兩個函數,會對把有真假值特性默認為false,而正常JS里都是true,如果定義的屬性不存在就會創建新的屬性!!
var obj1 = { }; Object.defineProperty(obj1,"name",{ configurable : true, //決定其他特性是否可以修改,包含直接刪除delete屬性值即value; enumerable : true, //是否可以枚舉 writable : true, //value 是否可以修改 value : "obama" //對象屬性真正保存值的地方,上面的都是對它的描述 } ); var obj1 = { name : "obama" }
上面的兩個對象是相等的,我們在直接些對象字面量的同時,JS引擎就默認生成了上面的屬性,我們也可以修改下
var obj1 = { }; Object.defineProperty(obj1,"name",{ configurable : true, enumerable : false, writable : true, value : "obama" } ); //下面的函數需要是枚舉特性才能使用 obj1.propertyIsEnumerable("name"); //false console.dir( Object.keys(obj1)); //數組是空 var properties; for(properties in obj1){ console.log("it has been search") // undefined } //*以下是誤區,in和hasOwnProperty函數查找的是否有屬性,不論是否可以枚舉* console.log("name" in obj1); //true console.log(obj1.hasOwnProperty("name")) //true
當然我們也可以同時定義多個屬性
var obj = { }; Object.defineProperties(obj,{ name:{ configurable : true, enumerable : true, writable : true, value : "obama" }, age :{ configurable : true, enumerable : true, writable : true, value : 77 }, behavior: { configurable : true, enumerable : true, writable : true, value : function(){ alert("i am the presdent of Amerca") } } }); obj = { name : "obama", age : 77, behavior : function(){ alert("i am the presdent of Amerca")} }
下面說說訪問器屬性,目前沒有方法,直接查看所有的特性,但是我們可以設置特性,和數據屬性使用一樣的方法,沒有value 和writable這兩個屬性,但是多[[get]]和[[set]]的方法;
//字面量 var obj = { _name : "obama", //使用下劃線_ 只是約定成俗的寫法,表示私有的(實際上我們也能訪問) get name(){ //get 后面的name就是我們可以訪問正常的屬性, return this._name; }, set name(value){ this._name = value; } }; //或者使用函數 var obj = { _name : "obama" }; Object.defineProperty(obj,"name",{ get : function (){ return this._name; }, set : function(value){ this._name = value; }, configurable : true, enumerable : true }) console.log(obj.name) //obama
訪問器屬性有趣的地方在于如果我們把get的方法換成其他,比如不返回它的值
get : function(){ return console.log(’i am Kim Jong-un‘); } obj.name //即使只是寫出這個屬性也會輸出’i am Kim Jong-un’
我們通過obj.name永遠得不到想要的值,當然這樣設置沒有任何意思,只是了解JS是如何取得屬性的值,
同時設置數據屬性和訪問器屬性是會得到一個錯誤。
屬性首次添加給對象時,JS就會在對象上調用[[Put]]方法,在對象內部開辟新的節點保存屬性,這個新屬性有默認的特性,重點是這個屬性僅會保存在這對象上,也就是說是這個對象的自有屬性!自有!自有![[Extensible]]方法,確定對象是否可以擴展,有三個具體的方法:
1,禁止擴展
var obj = { name : "obama" }; Object.preventExtensions(obj); obj.age = 77; console.log(obj.age) //undefined; //無法增加屬性,但是可以修改刪除原有屬性 Object.isExtensible(obj) //false 表示不可以擴展!
2,對象封印
var obj = { name : "obama" }; Object.seal(obj); //不僅不可以擴展也不可刪除屬性,只能讀寫 delete obj.name //false obj.name = " Kim Jong-un"; console.log(obj.name) // Kim Jong-un //可以修改屬性的writable(修改后只能讀取),只能true ->false,不能false ->true; Object.isSealed(obj); //true; Object.isExtensible(obj) //false;
3,對象凍結
var obj = { name : "obama" }; Object.freeze(obj); //凍結后只可以讀取值,,不可以修改刪除值 Object.isFrozen(obj) //true; Object.isSealed(obj); //true; Object.isExtensible(obj) //false;
對象還有一個實用的方法,Object.getOwnPropertyNames();在對象本身的屬性不可以枚舉的情況下也能列出,返回一個數組,對比Object.keys() 只能列舉可以枚舉的.
注:上面的例子在嚴格模式下會拋出錯誤,非嚴格模式會失敗
使用構造函數創建對象存在一個問題,就是必須使用new 操作符,構造函數也是函數如果直接調用的話,會把內部的this作用域指向全局;
function Fn(args){ this.args = args; } var obj1 = Fn("test"); obj1 //undefined args //test var obj2 = new Fn("test"); obj2.args //test; //安全的構造函數 function Fn(args){ if( this instanceof Fn){ this.args = args; }else{ return new Fn(args) } } //也可以使用Object.creat()的方法來創建對象 var obj1 = { }; var obj2 = Object.create(null); //obj2是一個真正意義上空的對象,沒有任何的繼承,比obj1更空,obj1繼承Object對象的屬性和方法。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/85164.html
摘要:所以覺得把這個執行的詳細過程整理一下,幫助更好的理解。類似的語法報錯的如下圖所示三預編譯階段代碼塊通過語法分析階段之后,語法都正確的下回進入預編譯階段。另開出新文章詳細分析,主要介紹執行階段中的同步任務執行和異步任務執行機制事件循環。 一、概述 js是一種非常靈活的語言,理解js引擎的執行過程對于我們學習js是非常有必要的。看了很多這方便文章,大多數是講的是事件循環(event loo...
摘要:所以覺得把這個執行的詳細過程整理一下,幫助更好的理解。類似的語法報錯的如下圖所示三預編譯階段代碼塊通過語法分析階段之后,語法都正確的下回進入預編譯階段。另開出新文章詳細分析,主要介紹執行階段中的同步任務執行和異步任務執行機制事件循環。 一、概述 js是一種非常靈活的語言,理解js引擎的執行過程對于我們學習js是非常有必要的。看了很多這方便文章,大多數是講的是事件循環(event loo...
摘要:以下知識點是前輩師兄總結基礎語義化標簽引進了一些新的標簽,特別注意等,注意的標題結構理解瀏覽器解析的過程,理解的樹形結構,及相應理解標簽在各個瀏覽器上的默認樣式代理樣式,理解中的重置樣式表的概念理解等功能性標簽理解標簽,理解文件提交過程推薦 以下知識點是前輩師兄總結 1、HTML/HTML5基礎: 1.0、語義化H5標簽1.1、H5引進了一些新的標簽,特別注意article...
摘要:以下知識點是前輩師兄總結基礎語義化標簽引進了一些新的標簽,特別注意等,注意的標題結構理解瀏覽器解析的過程,理解的樹形結構,及相應理解標簽在各個瀏覽器上的默認樣式代理樣式,理解中的重置樣式表的概念理解等功能性標簽理解標簽,理解文件提交過程推薦 以下知識點是前輩師兄總結 1、HTML/HTML5基礎: 1.0、語義化H5標簽1.1、H5引進了一些新的標簽,特別注意article...
摘要:至此作用域鏈創建完畢。好了,通過深入理解作用域鏈,我們能跟好的理解的運行機制和閉包的原理。 前言 理解javascript中的作用域和作用域鏈對我們理解js這們語言。這次想深入的聊下關于js執行的內部機制,主要討論下,作用域,作用域鏈,閉包的概念。為了更好的理解這些東西,我模擬了當一個函數執行時,js引擎做了哪些事情--那些我們看不見的動作。 關鍵詞: 執行環境 作用域 作用域鏈 變...
20190124問: 如何理解es6中的Proxy? 試題解析:對proxy的理解,可能會延伸到vue的雙向綁定 Proxy(代理) 定義 可以理解為為目標對象架設一層攔截,外界對該對象的訪問,都必須通過這層攔截 簡單示例: const obj = new Proxy({}, { get: (target, key, receiver) => { return JS ...
閱讀 1706·2021-11-24 09:39
閱讀 2489·2021-11-18 10:07
閱讀 3668·2021-08-31 09:40
閱讀 3341·2019-08-30 15:44
閱讀 2637·2019-08-30 12:50
閱讀 3658·2019-08-26 17:04
閱讀 1435·2019-08-26 13:49
閱讀 1271·2019-08-23 18:05