JS学习之-构造函数与原型对象一
构造函数特点:
1:首字母尽量大写,(区别于普通函数)
2:必须使用new 运算符调用
例如:
function Box(name,age){
this.name = name;
this.age = age;
this.run = function(){
return this.name+this.age+'正在运行中...';
}
}
var box1 = new Box(‘兰小宇’,200);
var box1 = new Box(‘兰小宇’,200);
alert(box1.run()); //输出 兰小宇200正在运行中...
alert(box2.run()); //输出 兰小宇200正在运行中...
//对比一下 box1和box2
第一次:比较他们的对象属性
alert(box1.name == box2.name); //输出 true
alert(box1.age == box2.age); //输出 true
第二次:比较他们的对象方法
alert(box1.run == box.run); //输出 false
解释:
第一次,比较的是他们对象属性的值,他们的值肯定是相等的因为传递是相等的
第二次,比较的是他们的对象方法,这里比较的是他们的引用地址,所以是不等的
图解如下:
以上是构造函数的声明和使用
---------------------------------------------------------------------------
然后我们看下原型
先看图
第一种:
用使用构造函数创建原型对象
备注:(给构造函数的原型添加对象属性和对象方法,需要使用prototype属性,这个属性是一个对象,prototype 通过 调用构造函数而创建的那个对象的原型。使用原型的好处可以让所有对象实例共享它所 包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息 添加到原型中。 )
function Box(){}; //创建构造函数
Box.prototype.name = '兰小宇'; //为Box构造函数的原型用字面量方式添加对象属性
Box.prototype.age = 100; //为Box构造函数的原型用字面量方式添加对象属性
Box.prototype.run = function(){ //为Box构造函数的原型用字面量方式添加对象方法
return this.name+this.age+'正在运行中.....';
}
var box1 = new Box(); //实例化构造函数
var box2 = new Box(); //实例化构造函数
alert(box1.run == box2.run); //输出 ture ,这个时候他们的地址都指向了原型里面的同一个对象方法所以是一致的
另外在原型中有两个自动生成的属性分别是__proto__和constructor,
其中__proto__ 属性是实例指向原型对象的一个指针,它的作用就是指向构造函数的原型属性 constructor
alert(box1.__proto__); //输出 [objectObject]
------------------》知识点
判断一个对象是否指向了该构造函数的原型对象,可以使用 isPrototypeOf()方法来测试。
例如:
function Box(){}; //创建构造函数
Box.prototype.name = '兰小宇'; //为Box构造函数的原型用字面量方式添加对象属性
Box.prototype.age = 100; //为Box构造函数的原型用字面量方式添加对象属性
Box.prototype.run = function(){ //为Box构造函数的原型用字面量方式添加对象方法
return this.name+this.age+'正在运行中.....';
}
var box =new Box();
alert(Box.prototype.isPrototypeOf(box)); //只要实例化对象,即都会指向
------------------》知识点
原型模式的执行流程:
1.先查找构造函数实例里的属性或方法,如果有,立刻返回;
2.如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回;
例如:
function Box(){}; //创建构造函数
Box.prototype.name = '兰小宇'; //为Box构造函数的原型用字面量方式添加对象属性
Box.prototype.age = 100; //为Box构造函数的原型用字面量方式添加对象属性
Box.prototype.run = function(){ //为Box构造函数的原型用字面量方式添加对象方法
return this.name+this.age+'正在运行中.....';
}
var box1 = new Box();
alert(box1.name); //输出 兰小宇 //这里取的是原型里面的属性
box1.name = '张三';
alert(box1.name); //输出 张三 //这里取得是构造函数里面的属性,就近原则
var box2= newBox();
alert(box2.name); //输出 兰小宇,原型里的值,没有被 box1 修改
--------------------》知识点
如何判断属性是在构造函数的实例里,还是在原型里?可以使用 hasOwnProperty()函数 来验证:
alert(box1.hasOwnProperty('name')); //实例里有返回 true,否则返回 false
图解三:
另外 in操作符会在通过对象能够访问给定属性时返回 true,无论该属性存在于实例中还是原型中。
alert('name' in box1); //true,存在实例中或原型中
以上是我们通过构造函数来创建原型
下面我们用字面量的方式来声明原型
function Box(){}; //创建构造函数
Box.prototype = {
name:'兰小宇',
age:200,
run:function(){
return this.name+this.age+'正在运行中...';
}
}
使用构造函数创建原型对象和使用字面量创建对象在使用上基本相同,但还是有一些区别,
字面量创建的方式使用 constructor 属性不会指向实例,而会指向 Object,构造函数创建 的方式则相反。
例如:
var box=new Box();
alert(box instanceof Box);
alert(box instanceof Object);
alert(box.constructor== Box); //字面量方式,返回 false,否则,true
alert(box.constructor== Object); //字面量方式,返回 true,否则,false
如果想让字面量方式的 constructor 指向实例对象,那么可以这么做:
Box.prototype={
constructor:Box, //直接强制指向即可
};
字面量方式为什么 constructor 会指向 Object?
因为 Box.prototype={};这种写法其实 就是创建了一个新对象。
而每创建一个函数,就会同时创建它 prototype,这个对象也会自 动获取 constructor 属性。
所以,新对象的 constructor 重写了 Box 原来的 constructor,
因此会 指向新对象,那个新对象没有指定构造函数,那么就默认为 Object
function Box(){};
Box.prototype={
constructor:Box,
name:'兰小宇',
age:100,
run:function(){
return this.name + this.age+'运行中...';
}
};
Box.prototype={
age:200 //原型被重写
};
var box=new Box(); //在这里声明
alert(box.run()); //输出undfinde。因为 重写的原型里面没有run方法
未完待续.....................