JavaScript進階程式設計(第三版)學習筆記6、7章,javascript學習筆記
第6章,物件導向的程式設計
對象:
1、資料屬性
configurable,表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或能否把屬性修改為訪問器屬性,預設為true
enumerbale,表示能否通過for-in訪問屬性,預設true
writable,表示能否修改屬性值,預設true
value,資料存放區位置,預設undefined
修改預設屬性特性:Object.defineProperty(),接收三個參數:屬性所在對象,屬性名稱,描述符對象,描述符對象屬性必須是:configurable、enumerable、writable、value
例:
var obj = {};Object.defineProperty(obj,”name”,{writable:true,value:”nihao”});
2、訪問器屬性
configurable,表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或能否把屬性修改為訪問器屬性,預設為true
enumerbale,表示能否通過for-in訪問屬性,預設true
get,讀取屬性時調用,預設undefined
set,寫入屬性時調用,預設undefined
修改必須通過Object.defineProperty()
例:
var obj = {_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;}}});book.year = 2005;alert(book.edition); //2
定義多個屬性:Object.defineProperties(),接收兩個對象,一是要修改和添加屬性的兌現,第二個對象屬性與第一個對象要修改或添加的屬性一一對應,支援的瀏覽器:IE9+,FireFox4+,Safari5+,Opera12+,chrome
讀取屬性:Object.getOwnPropertyDescriptor(),接收兩個參數,屬性所在對象,要讀取描述符的屬性名稱,支援的瀏覽器:IE9+,FireFox4+,Safari5+,Opera12+,chrome
建立對象:
原廠模式:
function createPerson(name,age){var o = new Object();o.name = name;o.age = age;o.sayName = function(){alert(this.name);};return o;}var person1 = createPerson(“g”,29);
建構函式模式:
function Person(name,age){this.name = name;this.age = age;this.sayName() = function(){alert(this.name);};}var person = new Person(“g”,28);
兩種模式區別:
建構函式模式中不需要顯示建立對象,對this直接賦值,沒有返回語句
建構函式名首字母必須大寫,必須使用new操作符建立新執行個體
原型模式
建立的每個函數都有一個prototype(原型)屬性,這個屬性是一個指標,指向一個對象,這個對象的用途是包含可以由特定類型的所有執行個體共用的屬性和方法,換句話就是,prototype就是通過函數建立的對象的原型對象,好處在於可以是所有執行個體共用相同的屬性和方法。
isPrototypeOf(),個人理解就是可以用以判斷某個執行個體的原型是否與當前原型相同
例:
Person.prototype.isPrototypeOf(person1); //true
Object.getPrototypeOf(),可以返回某個執行個體的原型,支援的瀏覽器IE9+,Firefox3.5+,Safari5+,Opera12+,chrome
註:訪問對象屬性名稱時會進行一次搜尋,先在執行個體對象搜尋,不存在則到當前對象的原型對象去搜尋。
註:執行個體中的屬性若與原型對象中的屬性一樣,則會屏蔽原型對象的屬性,與上一條剛好可以對的上
hasOwnProperty()方法可以確定某個屬性是否來自執行個體,不是來自執行個體,則返回false,否則返回true
在執行個體上調用delete時,只會刪除執行個體上的屬性名稱,並不會刪除原型的屬性
例:
function Person(){}Person.prototype.name = "Nicholas";Person.prototype.age = 29;Person.prototype.sayName = function(){alert(this.name);}var per1 = new Person();var per2 = new Person();per1.name = "Greg";alert(per1.name); //"Greg" 來自執行個體alert(per2.name); //"Nicholas"delete per1.name;alert(per1.name); //"Nicholas" 來自原型delete per1.name;alert(per1.name); //"Nicholas"
註:Object.getOwnPropertyDescriptor()方法只能用於執行個體屬性,要取得原型屬性描述符,必須直接在原型對象上調用本方法
in操作符:只有當屬性在執行個體對象中或者在原型對象中時,返回true
例:
alert(“name” in Person); //truealert(“name” in per1); //true
同時使用in和hasOwnProperty可以確定該屬性是存在原型中,還是執行個體中
Object.keys()方法:接收一個對象作為參數,返回所有可枚舉的屬性群組成的字串數組
Object.getOwnPropertyNames()方法:接收一個對象,返回所有屬性群組成的字串數組,無論是否可枚舉
更簡單的原型文法:
使用上述方法實在太麻煩了,更經常使用的是以下方法:使用對象字面量
Person.prototype = {name : “Nicholas”,age : 29sayName = function(){alert(this.name);}}
不過,此方法,相當於重寫了整個prototype對象,將導致constructor屬性不再指向Person而是指向Object,雖然instanceof還是會返回正確的結果,但通過constructor已經不能確定物件類型了。
var per = new Person();alert(per instanceof Object); //truealert(per instanceof Person); //truealert(per constructor Object); //truealert(per constructor Person); //false
若constructor真的很重要,可以如下設定
Person.prototype = {constructor:Person,name : “Nicholas”,age : 29sayName = function(){alert(this.name);}}
以上寫法會使constructor的enumerable特性被設定為true,預設情況下原生的是false的,在相容ECMAScript5的瀏覽器可以使用Object.defineProperty()進行設定
Object.defineProperty(Person.prototype,”constructor”,{enumerable:false,value:Person});
註:重寫原型對象,將會切斷現有原型與任何之前已經存在的對象執行個體之間的聯絡
繼承(難度較大,需再仔細研究)
使用原型鏈來實現
子類型要覆蓋超類的方法,應該將給原型添加方法的代碼放在替換原型之後,
註:通過原型鏈實現繼承時,不能使用對象字面量建立原型方法,否則會重寫原型鏈
借用建構函式
組合繼承
原型式繼承,Object.creat();接收兩個參數:一是用作新對象原型的對象和(可選的)一個為新對象定義額外屬性的對象
例:Object.creat(person,{name:{value:”greg”}});
寄生式繼承
寄生組合式繼承
第7章,函數運算式
建立方式:
1、函式宣告,可以函式宣告提升,就是可以把使用函數的語句放在函式宣告之前
function funName(arg0,arg1){//函數體}
2、函數運算式,不能進行函數提升,也就是無法在函數建立前使用函數,在這種情況下建立的函數稱為匿名函數,有時也叫拉姆達函數
var funName = function(arg0,arg1){//函數體}
strict 模式下無法使用arguments.callee來實現遞迴,可以使用如下方式實現遞迴:
var factorial = (function f(num){if(num <= 1){return 1;}else{return num * f(num - 1);}});
閉包(難度也不小)
閉包指有權訪問另一個函數範圍中的變數的函數,閉包,也是一個函數
建立閉包的常見方式是在一個函數內部建立另一個函數
閉包只能取得包含函數即外部函數中任何變數的最後一個值。下例可以清晰說明問題
例:
function createFuncrions(){var result = new Array();for(var i = 0;i < 10;i++){result[i] = function(){return i;}}return result;}var re = createFuncrions();alert(re[1](2));
每個函數返回的都將是10,而不是如預期般返回對應的索引值,因為createFuncrions函數最後返回時I = 10,此時每個函數都引用儲存著變數i的同一個對象,所以在每個函數內部i都是10,可以使用如下方法強制閉包返回預期效果:
function createFuncrions(){var result = new Array();for(var i = 0;i < 10;i++){result[i] = function(num){return function(){return num;};}(i);}return result;}var re = createFuncrions();alert(re[2]());
每一個都會返回各自的索引值
模仿塊級範圍
使用匿名函數可以模仿塊級範圍:
(function(){alert("test"); //塊級範圍,沒有使用圓括弧將function包起來將會出錯})();
使用閉包和私人變數的明顯不足之處在於,會在範圍鏈中多尋找一個層次,在一定程度上影響尋找速度
函數中定義的變數可以在一定程度上稱為私人變數,通過函數可以類比出私人變數,靜態私人變數
增強模組模式:
var singleton = function(){//private arg and private methodvar privateVariable = 10;function privateFunction(){return false;}//create objvar obj = new Object();obj.publicProperty = true;obj.publicFunction = function(){privateVariable ++;return privateFunction();};return obj;}();alert(typeof singleton);alert(singleton.publicProperty);alert(singleton.publicFunction());
以上內容是小編給大家介紹的JavaScript進階程式設計(第三版)學習筆記6、7章,希望對大家有所協助!
您可能感興趣的文章:
- JavaScript進階程式設計 DOM學習筆記
- JavaScript進階程式設計 XML、Ajax 學習筆記
- JavaScript進階程式設計 事件學習筆記
- JavaScript進階程式設計(第3版)學習筆記 概述
- JavaScript進階程式設計(第3版)學習筆記2 js基礎文法
- JavaScript進階程式設計(第3版)學習筆記3 js單一資料型別