在了解如何使用原型模式建立对象以前,有必要先搞清楚什么是原型对象。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 共享函数
以上,在构造函数中定义实例属性,在原型中定义共享属性的模式,是目前使用最普遍的方式。一般状况下,咱们都会默认使用这种方式来定义引用类型变量。