在JavaScript中,函數時一個包括屬性和方法的Function類型的對象。而原型(Prototype)就是Function類型對象的一個屬性。
在函數定義時就包含了protoype屬性,它的初始值是一個空對象。在JavaScript中並無定義函數的原始類型,因此原型能夠是任何類型。
原型是用於保存對象的共享屬性和方法的,原型的屬性和方法並不會影響函數自己的屬性和方法。數組
Function類型的屬性 -> 全部函數都具備的屬性 console.log(Function.prototype); // 定義函數 function fn(){ console.log('this is function'); } // 原型的默認值是空對象 console.log(fn.prototype); // 函數包含構造函數 -> 全部引用類型其實都是構造函數 console.log(Number.prototype); console.log(Object.prototype); var result = Object.getOwnPropertyDescriptor(Object.prototype, 'constructor'); console.log(result);
經過下面代碼方式獲取對象的原型,從而設置共享的屬性和方法。函數
function fn(){ console.log('this is function'); } // 使用訪問對象的屬性語法結構 console.log(fn.prototype); console.log(fn['prototype']); // Object類型提供getPrototypeOf()方法 console.log(Object.getPrototypeOf(fn));
function fn(){ console.log('this is function'); } // 變量proto也是一個空對象 // var proto = fn.prototype; // 新增屬性或方法 // proto.name = '張無忌'; fn.prototype.name = '張無忌'; console.log(fn.prototype); // defineProperty() Object.defineProperty(fn.prototype, 'age', { value : 18, enumerable : true }); console.log(fn.prototype);
1.自有屬性:經過對象的引用添加的屬性。其餘對象可能無此屬性;即便有,也是彼此獨立的屬性。
2.原有屬性:從原型對象中繼承來的屬性,一旦原型對象中屬性值改變,全部繼承自該原型的對象屬性均改變。this
// 定義構造函數 function Hero(){ this.name = '張無忌'; this.sayMe = function(){ console.log('this is function'); } } // 操做構造函數Hero的原型 Hero.prototype.age = 18; // 利用構造函數來建立對象 var hero = new Hero(); console.log(hero); // 爲構造函數的原型新增的屬性 -> 構造函數建立的對象中依舊能夠訪問 console.log(hero.age);// 18 // 對象hero中不存在age屬性 var result = Object.getOwnPropertyDescriptor(hero, 'age'); console.log(result);
function Hero(){ // this.name = '張無忌';// 自有屬性 } // Hero.prototype.name = '周芷若'; var hero = new Hero(); /* Object.hasOwnProperty(prop)方法 * 做用 - 判斷當前指定屬性是否爲自有屬性 * 參數 * prop - 表示指定屬性名稱 * 返回值 - 布爾值 * true - 表示存在指定的自有屬性 * false - 表示不存在指定的自有屬性 */ // console.log(hero.hasOwnProperty('name'));// true /* 使用in關鍵字檢測對象的屬性 * 做用 - 判斷對象中是否存在指定屬性(自有屬性或原型屬性) * 返回值 - 布爾值 * true - 表示存在指定的屬性 * false - 表示不存在指定的屬性 */ console.log('name' in hero);
經過原型能夠爲指定構造函數或對象擴展其屬性或方法。prototype
function fn(){ console.log('this is function'); } // 變量proto也是一個空對象 // var proto = fn.prototype; // 新增屬性或方法 // proto.name = '張無忌'; fn.prototype.name = '張無忌'; console.log(fn.prototype); // defineProperty() Object.defineProperty(fn.prototype, 'age', { value : 18, enumerable : true }); console.log(fn.prototype);
經過構造函數或對象的自有屬性能夠重寫原型的屬性調試
// 定義構造函數 function Hero(){ this.name = '張無忌'; } // 構造函數的原型 Hero.prototype.name = '周芷若'; // 構造函數建立對象 var hero = new Hero(); // 自有屬性與原型屬性同名時,默認訪問的是自有屬性 -> 自有屬性的優先級別高於原型屬性 console.log(hero.name);// 張無忌 // 刪除對象的屬性 delete hero.name; // 從新訪問對象的屬性 console.log(hero.name);// 周芷若
經過delete關鍵字能夠刪除對象的屬性,若是該對象即具備原型屬性又具備自有屬性,首先就要刪除自有屬性,再刪除原型屬性。code
function Hero(){} Hero.prototype = { name:'Mary',salary:3800 }; var hero = new Hero(); hero.name = "Tom"; delete hero.name;//刪除Tom console.log(hero.name);//Mary delete hero.name;//刪除Mary console.log(hero.name);//undefined
每一個對象中都會基友一個isPrototypeOf()方法,該方法用來判斷一個對象是不是另外一個對象的原型。對象
// 經過初始化器方式定義對象 var obj = { name : '張無忌' } // 定義構造函數 function Hero(){} // 將對象obj賦值給構造函數Hero的原型 Hero.prototype = obj; // 經過構造函數建立對象 var hero = new Hero(); // 判斷指定對象是不是另外一個對象的原型 var result = obj.isPrototypeOf(hero); console.log(result);
——proto——屬性繼承
// 經過初始化器方式定義對象 var obj = { name : '張無忌' } // 定義構造函數 function Hero(){} // 將對象obj賦值給構造函數Hero的原型 Hero.prototype = obj; // 經過構造函數建立對象 var hero = new Hero(); // 判斷指定對象是不是另外一個對象的原型 var result = obj.isPrototypeOf(hero); console.log(result);
上述代碼中說明hero對象存在一個指向構造函數Hero的原型,這個連接被叫作——proto——屬性。
須要注意的是——proto——屬性與prototype屬性並不等價。——proto——屬性只能調試時使用。
——proto——屬性是指定對象的屬性。
prototype屬性是指定構造函數的屬性。ip
JavaScript中的內置對象有些也具備prototype屬性,利用內置對象的prototype屬性能夠爲內置對象擴展屬性或方法。
經過原型擴展內置對象的屬性和方法很是靈活,根據個性化要求制定JavaScript語言的具體內容。通常建議謹慎使用這種方法,若是JavaScript的版本更新是可能會提供個性化的屬性或方法,致使衝突。get
Object.prototype.sayMe = function(){ console.log('this is sayMe function'); } // 經過Object構造函數建立對象 var obj = new Object(); obj.sayMe(); Array.prototype.inArray = function(color){ // this - 表示當前的數組 for(var i = 0, len = this.length; i < len; i++){ if(this[i] === color){ return true; } } return false; } var arr = ["red", "green", "blue"]; console.log(arr.inArray("red")); //true console.log(arr.inArray("yellow")); //false