javascript學習

關於javascript中對象的理解

其實,javascript中的對象就類似於java中所說的對象,區別就在於,javascript對象中的屬性有類型的區分:

1、數據屬性

數據屬性包含一個數據值的位置,在這個位置可以讀取和寫入值。

屬性的特性:
[[Configurable]]:表示能否通過delete 刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改爲訪問器屬性--默認爲true;
[[Writable]]:表示能否修改屬性的值--默認爲true;
[[Value]]:包含這個屬性的數據值--默認爲undefined;

[[Enumerable]]:表示能否通過for-in循環返回屬性--默認爲true。

e.g.

	//創建了一個名爲name的屬性,爲它指定的值,也就是[[Value]]特性將被設置爲"Jack"
	var person = {
		name:"Jack"
	};

修改方法

要想修改屬性默認的特性,必須使用Object.defineProperty()方法
e.g.
		//接受三個參數,屬性所在的對象,屬性的名字和一個描述符對象,描述符必須是:configurable、enumerable、writable和value中的一個或多個
		//注意:一旦將configurable設置爲false,就不能再把它變回可配置的了。在調用該方法是,如果不指定,configurable、enumerable、writable默認爲false
		Object.defineProperty(person,"name",{
			writable:false,
			value:"James"
		});
		alert(person.name);//"James"
		person.name="George";
		alert(person.name);//"James"

2、訪問器屬性

該屬性不包含數據值,它包含一對getter和setter函數(這兩個函數都不是必需的)
屬性的特性:
[[Configurable]]:表示能否通過delete 刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改爲訪問器屬性--默認爲true
[[Enumerable]]:表示能否通過for-in循環返回屬性--默認爲true
[[Get]]:在讀取屬性時調用的函數--默認爲undefined
[[Set]]:在寫入屬性時調用的函數--默認爲undefined

並且,訪問器屬性是不能直接定義的,必須使用Object.defineProperty()來定義。

e.g.

		var book = {
			_year:2004,
			edition:1
		};

		Object.defineProperty(book,"year",{
			get:function(){
				return this._year;
			},
			set:function(newValue){
				if(newValue > 2004){
					this._year = newValue;
					this.edition += newValue - 2004;
				}
			}
		});
針對這些屬性的特性,javascript還有相應的讀取屬性特性的方法:Object.getOwnPropertyDescriptor()方法。

e.g.

	var descriptor = Object.getOwnPropertyDescriptor(book,"_year");//讀取屬性特性

創建對象

1、工廠模式

	//該模式抽象了創建具體對象的過程,用函數來封裝以特定接口創建對象的細節。
	function createPerson(name,age,job){
		var o = new Object();
		o.name = name;
		o.age = age;
		o.job = job;
		o.sayName = function(){
			alert(this.name);
		};
		return o;
	}

2、構造函數模式

	function Person(name,age,job){
		this.name = name;
		this.age = age;
		this.job = job;
		this.sayName = function(){
			alert(this.name);
		};
	}

	/*
	 * 創建對象的新實例,必須使用new操作符,經歷的具體步驟如下:
	 * 1、創建一個新的對象
	 * 2、將構造函數的作用域賦給新對象(因此this就指向了這個新對象)
	 * 3、執行構造函數中的代碼(爲這個對象添加屬性)
	 * 4、返回新對象--不需要return語句
	 */
	var person2 = new Person("Jerry",22,"Engineer");
與工廠模式的區別:
  •  沒有顯示地創建對象
  • 直接將屬性和方法賦給了this對象
  • 沒有return語句

3、原型模式

我們創建的每一個函數都有一個prototype屬性,這個屬性是一個指針,指向一個對象,這個對象包含 可以由特定類型的所有實例共享的屬性和方法。
對於原型對象的理解,書上講的都比較繞,通過代碼結合一張圖,就能比較方便地理解了。
function Person(){
}
Person.prototype.name = "Jack";
Person.prptotype.age = 22;
Person.prototype.job = "Sofyware Engineer";
Person.prototype.sayName = function(){
	alert(this.name);
};

var person1 = new Person();
var person2 = new Person();

person1.name = "George";
alert(person1.name);//"George"--來自實例
alert(person2.name);//"Jack"--來自原型

讀取對象屬性,就又是其中的一個比較重點的東西了。
每當代碼讀取一個對象的某個屬性時,都會執行一次搜索,目標是具有給定名字的屬性。
搜索首先從對象實例本身開始,如果在實例中找到了具有給定名字的屬性,那麼停止搜索,返回該屬性;
否則繼續搜索指針指向的原型對象,在原型對象中查找具有給定名字的屬性。

注意:雖然可以通過對象實例訪問保存在原型對象中的屬性的值,但卻不能通過對象實例重寫原型對象中的屬性的值。

這裏又有一個新的概念:屏蔽。

如果我們在實例中添加了一個屬性,並且這個屬性又恰好跟實例原型中的某一屬性同名,那我們在實例中創建該屬性,該屬性就將會屏蔽原型中的同名屬性。

有關原型模式的其他方法:

hasOwnProperty():可以檢測一個屬性是否存在於實例中,還是存在於原型中--當屬性存在於對象實例中時,纔會返回true(該方法繼承自Object)

in操作符:

in操作符有兩種使用方式:

1、在for-in循環中使用;

2、單獨使用:in操作符會在 通過對象可以訪問到指定屬性值時返回true,不管這個屬性是對象實例中的還是原型中的。

function Person(){
}
Person.prototype.name = "Jack";
Person.prptotype.age = 22;
Person.prototype.job = "Sofyware Engineer";
Person.prototype.sayName = function(){
	alert(this.name);
};

var person1 = new Person();
var person2 = new Person();

person1.name = "George";
alert(person1.name);//"George"--來自實例
alert(person2.name);//"Jack"--來自原型

alert(person2.hasOwnProperty("name"));//false
alert("name" in person2);//true

delete person1.name;
alert(person2.hasOwnProperty("name"));
alert("name" in person2);//true
根據上面的東西,總結了一個小技巧。

當屬性的in操作符返回true而hasOwnProperty()返回false時,就可以確定屬性是原型中的屬性。

發佈了46 篇原創文章 · 獲贊 42 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章