原文地址:js面向對象學習筆記
一、對象概念
對象是什么?對象是“無序屬性的集合,其屬性可以包括基本值,對象或者函數”。也就是一組名值對的無序集合。
對象的特性(不可直接訪問),也就是屬性包含兩種,數據屬性和訪問器屬性。
1、數據屬性又包含
- Configurable //表示能否通過delete刪除,默認為true;
- Enumerable //表示能否通過for-in循環返回屬性,默認為true;
- Writable //表示能否修改屬性的值,默認為true;
- Value //包含屬性的數據值,默認為undefined
要修改默認屬性的特性,必須使用ECMAscript5的object.defineProperty(屬性的對象, 屬性的名字, 需要修改的屬性特性)方法。例如:
// 1、修改默認的屬性特性,
var person = {};
Object.defineProperty(person, "name", {
writable : false,
value : "abc"
});
alert(person.name); //abc
person.name = "bcd";
alert(person.name); //abc而不是bcd,這里在非嚴格模式下會忽略,在嚴格模式下會報錯
一旦做了這樣的設置之后,就不可再次修改了,否則就會報錯。
// 1、修改默認的屬性特性,
var person = {};
Object.defineProperty(person, "name", {
writable : false,
value : "abc"
});
Object.defineProperty(person, "name", {
writable : true,
});

還有一點要注意的是,在調用Object.defineProperty()方法時,如果不指定第三個參數中的(Configurable,writable,Enumerable),也就是要修改的屬性,那么他們都會默認為false
// 1、修改默認的屬性特性,
var person = {};
person.sex = "nan";
Object.defineProperty(person, "name", { //在這里我們修改name的值,不指定第三個參數中的屬性,看結果
// writable : false,
value : "abc"
});
alert(person.name); //abc
person.name = "bcd";
alert(person.name); //abc,不可修改,默認為false
person.sex = "nv"; //沒有調用defineProperty,默認還是為true
alert(person.sex); //nv
2、訪問器屬性
- Configurable
- enumerable
- get //在讀取屬性時調用的函數
- set //在寫入屬性時調用的函數
// 2、定義訪問器屬性
var book = {
_year : 2014,
edition : 1
}
Object.defineProperty(book, 'year', { //year在這里就是定義訪問器屬性
get : function(){
return this._year;
},
set : function(value){
this._year = value;
this.edition += value-2004;
}
});
book.year = 2005;
alert(book.edition); // 2
當需要定義多個屬性時,可以使用defineProperties(對象, 需要添加的屬性);
// 3、定義多個屬性
var books = {};
Object.defineProperties(books, {
_year : {
value : 2004
},
edition : {
value : 1
},
year : {
get : function(){
return this._year;
},
set : function(value){
this._year = value;
this.edition += value-2004;
}
}
});
// books.year = 2006;
// alert(books._year); ////這里就不能用這個方法賦值了,這里返回2004
var descriptor = Object.getOwnPropertyDescriptor(books, "_year");
descriptor.value = 2006;
alert(descriptor.value); //2006
// alert(typeof descriptor.get);
這些概念似乎用的地方比較少,但是去理解js對象是很有作用的,基礎嘛,基礎永遠是必須的,繼續學習~
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/*==========================================================================*/
(我發現等號分割線沒上面短杠分割線好看)
二、創建對象
前幾天看到這樣的面試題,js創建對象的方法有幾種,只知道是3種寫法,並不清楚原理是什么,今天整理了下。
- 工廠模式
- 構造函數模式
- 原型模式
- 組合使用構造函數模式和原型模式
1、工廠模式
// 4、工廠模式
function createPerson(name){
var obj = new Object();
obj.name = name;
obj.show = function(){
alert(this.name);
}
return obj;
}
var person = createPerson("ym");//不需要使用new
person.show();
2、構造函數模式
構造函數的函數名大寫開頭,其他函數都是小寫
// 5、構造函數模式
function Person(name, sex){
this.name = name;
var sex = sex; //私有
this.show = function(){
alert(sex);
}
}
var person1 = new Person('ym', 'nan');
alert(person1.name); //ym
alert(person1.sex); //undefined
person1.show(); //nan
與工廠模式的區別:
- 沒有顯示創建對象
- 直接賦值給this對象
- 沒有return語句
構造函數的問題:
當對象有多個實例時,這些實例的所有方法都是不同的,因為它都會創建一遍。
// 5、構造函數模式
function Person(name, sex){
this.name = name;
var sex = sex; //私有
this.show = function(){
alert(sex);
}
}
var person1 = new Person('ym', 'nan');
var person2 = new Person('jh', 'nv');
// alert(person1 instanceof Person); //true
alert(person1.show == person2.show); //false
3、原型模式
優點:可以讓所有對象實例共享它所包含的屬性和方法。
// 6、原型模式
function Person2(){}
Person2.prototype = {
name : "ym",
sex : 'nan',
show : function(){
alert(this.name);
}
}
var a = new Person2();
var b = new Person2();
alert(a.show == b.show); //true
關於prototype,對它的理解也是非常重要的,過幾天再學習整理,看了好多次了,覺得還是理解不夠。
prototype是一個指針,指向一個對象,而這個對象就是包含所有實例共享的屬性和方法,也就是說,通過調用構造函數而創建的那個對象實例的原型對象。
原型模式的問題:
// 6、原型模式
function Person2(){}
Person2.prototype = {
name : "ym",
sex : 'nan',
love : ['a', 'b'],
show : function(){
alert(this.name);
}
}
var a = new Person2();
a.love.push('c');
var b = new Person2();
a.love.push('d');
// alert(a.show == b.show);
alert(a.love); //abcd
alert(b.love); //abcd
4、組合使用原型模式和構造函數模式
通過以上的例子我們可以知道,構造函數模式,創建的方法都是不同的,都是實例自己擁有的,而原型模式定義的屬性和方法是共享的,那么結合起來使用真是perfect。
// 6、混合模式
function Perfect(name, sex){
this.name = name;
this.sex = sex;
this.love = ['a' , 'b'];
}
Perfect.prototype = {
constructor : Perfect,
show : function(){
alert(this.love);
}
}
var a = new Perfect('a', 'nan');
var b = new Perfect('b', 'nv');
a.love.push('c');
b.love.push('d');
a.show(); //abc
b.show(); //abd
總算是整理完了,我也理解了原來創建對象的3種方法就是上面說的前3點,但最好用的是第4種。
