在瞭解如何使用原型模式建立對象以前,有必要先搞清楚什麼是原型對象。javascript
咱們建立的每個構造函數都有一個prototype屬性,該屬性是一個指針,該指針指向了一個對象。對於咱們建立的構造函數,該對象中包含能夠由全部實例共享的屬性和方法。php
constructor 是每個對象的屬性html
由於 Function 在javacsript中是一個對象Object,又是全部方法的構造器.注意:java
,function Function(),function Object(),function Array(),function String(),function Student(),function Cat(),function abc()做爲對象,它們都是Function的實例對象。所以有construtor屬性,jquery
因此他們的構造器:Function.constructor === Object.constructor ===Array.constructor === Student.constructor === f Function()數組
function Object(),function Array(),function String(),function Student() 在javascript中既是Function的實例對象.又是object,array,string,stu的構造器.函數
爲此object,array,string,stu是對應Object,Array,String,Student的實例對象,因此網站
object.constructor=== f Object,array.constructor=== f Array,string..constructor=== f String,stu..constructor=== f Studentui
function Object(),function Array(),function String(),function Student()做爲構造函數時,this
Function.prototype爲何返回的又是一個函數?????
Object.prototype指向Object構造函數的原型對象,該原型對象中的一些屬性和方法是全部實例共享的,也就是全局的屬性和方法,例如toString ()、valueOf()
Array.prototype指向Array構造函數的原型對象,同上有全部實例共性的屬性個方法。也就是常見的數組方法和屬性。
String.prototype,Student.prototype等都是同理。
function Object(),function Array(),function String(),function Student()做爲構造函數時,它們的實例對象
object._proto_ === Object.prototype
array._proto_ === Array.prototype
string._proto_ === String.prototype
stu._proto_ === Student.prototype
constructor能夠被改寫,因此使用要當心。
在調用構造函數建立新的實例時,該實例的內部會自動包含一個[[Prototype]]指針屬性,該指針指便指向構造函數的原型對象。注意,這個指針關聯的是實例與構造函數的原型對象而不是實例與構造函數:
array的 constructor 屬性返回 function Array() { [native code] }
num 數字 constructor 屬性返回 function Number() { [native code] }
string constructor 屬性返回 returns function String() { [native code] }
var fruits = ["Banana", "Orange", "Apple", "Mango"];
var ary=fruits.constructor;
alert(ary);//彈出function Array() { [native code] }
alert(fruits.constructor===ary);//彈出true
alert(fruits.constructor===Array);//也是彈出true
所以:Student.prototype.constructor===Student
javascript中類型檢測方法有不少:
最多見的就是typeof:
比較特殊的是typeof null返回「object」。
歷史緣由,規範嘗試修改typeof null返回「null」修改完大量網站沒法訪問,爲了兼容,或者說歷史緣由返回"object"。
typeof會返回一個變量的基本類型,只有如下幾種:number,boolean,string,object,undefined,function;typeof對4種基本類型(number,boolean,undefined,string),function,object,很方便,可是其餘類型就沒辦法了。
1.javascript的typeof返回哪些數據類型
object number function boolean underfind.string
判斷一個對象是否是數組對象?用typeof返回「object」。
instanceof只能用來判斷對象和函數,不能用來判斷字符串和數字等,返回的是一個布爾值。instanceof是檢測左邊對象的原型鏈是否指向右邊構造函數的prototype屬性的,因此咱們也能夠用它來判斷:
ar b = '123';
alert(b instanceof String); //false,instanceof沒法判斷字符串
alert(typeof b); //string,tpyeof返回變量的基本數據類型
var c = new String("123");
alert(c instanceof String); //true,instanceof可判斷對象
alert(typeof c); //object,typeof判斷對象時都返回object
var arr = [1,2,3];
alert(arr instanceof Array); // true
instanceof在判斷對象是否是數組對象Array,String,Date,Number,Boolean正則等時很好用。
instanceof坑:不一樣window或iframe之間的對象類型檢測不能使用instanceof!
除了instanceof來判斷數組以外,還有就是數組對象的arr.constructor屬性。
在默認狀況下,全部原型對象會自動包含一個constructor屬性,該屬性也是一個指針,指向prototype所在的函數.這個屬性在咱們使用js系統或者本身建立的對象的時候,會默認的加上.
任何對象都有constructor屬性,繼承自原型的,constructor會指向構造這個對象的構造器或者構造函數。
constructor能夠被改寫,因此使用要當心。
var arr = [1,2,3]; //建立一個數組對象
alert(arr.constructor === Array); // true
可使用jquery的$.type()方法。
瞭解了原型對象以後,咱們即可以經過在構造函數原型對象中添加屬性和方法來實現對象間數據的共享了。例如:
function Student() {
}
Student.prototype.name = "easy";
Student.prototype.age = 20;
Student.prototype.alertName = function(){
alert(this.name);
};
var stu1 = new Student();
var stu2 = new Student();
stu1.alertName(); //easy
stu2.alertName(); //easy
alert(stu1.alertName == stu2.alertName); //true 兩者共享同一函數
以上代碼,咱們在Student的protptype對象中添加了name、age屬性以及alertName()方法。但建立的stu1和stu2中並不包含name、age屬性以及alertName()方法,而只包含一個[[prototype]]指針屬性。當咱們調用stu1.name或stu1.alertName()時,是如何找到對應的屬性和方法的呢?
當咱們須要讀取對象的某個屬性時,都會執行一次搜索。首先在該對象中查找該屬性,若找到,返回該屬性值;不然,到[[prototype]]指向的原型對象中繼續查找。
由此咱們也能夠看出另一層意思:若是對象實例中包含和原型對象中同名的屬性或方法,則對象實例中的該同名屬性或方法會屏蔽原型對象中的同名屬性或方法。緣由就是「首先在該對象中查找該屬性,若找到,返回該屬性值;」
擁有同名實例屬性或方法的示意圖:
上圖中,咱們在訪問stu1.name是會獲得」EasySir」:
alert(stu1.name); //EasySir
不少時候,咱們爲了書寫的方便以及直觀上的」封裝性」,咱們每每採用對象字面量直接重寫整個原型對象:
function Student() {
}
Student.prototype = {
constructor : Student,
name : "easy",
age : 20,
alertName : function() {
alert(this.name);
}
};
要特別注意,咱們這裏至關於用對象字面量從新建立了一個Object對象,而後使Student的prototype指針指向該對象。該對象在建立的過程當中,自動得到了新的constructor屬性,該屬性指向Object的構造函數。所以,咱們在以上代碼中,增長了constructor : Student使其從新指回Student構造函數。
原型模型在對象實例共享數據方面給咱們帶來了很大的便利,但一般狀況下不一樣的實例會但願擁有屬於本身單獨的屬性。咱們將構造函數模型和原型模型結合使用便可兼得數據共享和」不共享」。
咱們結合原型模式在共享方法屬性以及構造函數模式在實例方法屬性方面的優點,使用如下的方法建立對象:
//咱們但願每一個stu擁有屬於本身的name和age屬性
function Student(name, age) {
this.name = name;
this.age = age;
}
//全部的stu應該共享一個alertName()方法
Student.prototype = {
constructor : Student,
alertName : function() {
alert(this.name);
}
}
var stu1 = new Student("Jim", 20);
var stu2 = new Student("Tom", 21);
stu1.alertName(); //Jim 實例屬性
stu2.alertName(); //Tom 實例屬性
alert(stu1.alertName == stu2.alertName); //true 共享函數
以上,在構造函數中定義實例屬性,在原型中定義共享屬性的模式,是目前使用最普遍的方式。一般狀況下,咱們都會默認使用這種方式來定義引用類型變量。