建立对象
var box = new Object();//建立对象
box.name = 'Lee'; //增加属性
box.age = 100;
box.run = function(){
return this.name + this.age + "运转中"; //this 示意当前作用域下对象
}
// this 示意new Object()实例出来的谁人对象
alert(box.run());
这就是建立对象最基础的要领,然则有个瑕玷,想建立一个相似的对象,就会发生大批的代码。
工场形式
为了处理多个相似对象声明的题目,我们能够运用一种叫做工场形式的要领,这类要领就是为了处理实例化对象发生大批反复的题目。
function createObject(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function(){
return this.name+this.age+"岁岁数";
}
return obj;
}
var box1 = createObject('Lee',20);
var box2 = createObject('Jack',30);
console.log(box1.run());
console.log(box2.run());
工场形式处理了反复实例化的题目,但另有一个题目,那就是辨认题目,由于基础没法搞清他们究竟是哪一个对象的实例。
alert(typeof box1); //Object
alert(box1 instanceof Object);//true
组织函数
ECAMScript中采纳组织函数(组织要领)可用来建立特定的对象。相似于Object对象。
//组织函数
function Box(name,age){
this.name = name;
this.age = age;
this.run = function(){
return this.name + this.age +"运转中...";
};
};
var box1 = new Box('Lee',100);
var box2 = new Box('Jack',200);
console.log(box1.run());
console.log(box2.run());
运用组织函数的要领,即处理了反复实例化的题目,又处理了对象辨认的题目,但题目是,这里并没有new Object(),为何能够实例化Box(),这个是哪里来的呢?
运用了组织函数的要领,和运用工场形式的要领他们差别之处以下:
1.组织函数要领没有显现的建立对象(new Objectt()),但它在背景自动var obj = new Object();
2.直接将属性和要领赋值给this对象,this就相称于obj;
3.没有return语句,不需要返回对象援用,它是在背景自动返回的。
//组织函数
function Box(name,age){
this.name = name;
this.age = age;
this.run = function(){
return this.name + this.age +"运转中...";
};
};
function Dack(name,age){
this.name = name;
this.age = age;
this.run = function(){
return this.name + this.age +"运转中...";
};
};
var box1 = new Box('Lee',100);
var box2 = new Box('Jack',200);
var box3 = new Dack('MrLee',300);
console.log(box1.run());
console.log(box2.run());
console.log(box3.run());
//处理了对象辨认题目
console.log(box1 instanceof Box); //true
console.log(box2 instanceof Box); //true
console.log(box3 instanceof Box); //false
console.log(box3 instanceof Dack);//true
对象假装:运用call()要领
var o= new Object();
Box.call(o,'Lee',100);
console.log(o.run());
看下一个题目:
var box1 = new Box('Lee',100); //实例化后地点为1
var box2 = new Box('Lee',100); //实例化后地点为2
console.log(box1.name == box2.name); //true
console.log(box1.age == box2.age); //true
console.log(box1.run() == box2.run());//true //组织函数体内的要领的值是相称的
console.log(box1.run == box2.run); //false //由于他们比较的是援用地点
上面的代码运转申明援用地点不一样,那末组织函数内的要领也能够如许写:
this.run = new Function("return this.name + this.age +'运转
怎样让他们的援用地点一样,下面代码:
function Box(name,age){
this.name = name;
this.age = age;
this.run = run;
};
function run(){
return this.name +this.age+"运转中...";
}
var box1 = new Box('Lee',100); //实例化后地点为1
var box2 = new Box('Lee',100); //实例化后地点为2
console.log(box1.run == box2.run); //true //由于他们比较的是援用地点
把组织函数内部的要领经由历程全局来完成援用地点一致。
虽然运用了全局函数run()来处理了保证援用地点一致的题目,然则这类体式格局又带来了一个新的题目,全局中的this在对象挪用的时刻是Box自身,而当一般函数挪用的时刻,this又代表window。
原型
function Box(){
//组织函数函数体内什么都没有,这里如有过,叫做实例属性,实例要领
}
Box.prototype.name="Lee"; //原型属性
Box.prototype.age=100;
Box.prototype.run=function(){ //原型要领
return this.name+this.age+"运转中...";
}
var box1=new Box();
var box2=new Box();
console.log(box1.run == box2.run); //true
console.log(box1.prototype);//这个属性是一个对象,接见不到
console.log(box1.__proto__);//这个属性是一个指针指向prototype原型对象。
假如是实例要领,差别的实例化,他们的要领地点是不一样的,是唯一的。
假如是原型要领,那末他们的地点是同享的,人人都一样。
console.log(box1.constructor); //组织属性,能够猎取组织函数
PS:IE浏览器在剧本接见__proto__会不能辨认,火狐和谷歌及其他某些浏览器能辨认。虽然能够输出,然则没法猎取内部信息。
推断一个对象是不是指向该组织函数的原型对象,能够运用isPrototypeOf()要领来测试。
console.log(Box.prototype.isPrototypeOf(box1)); //true //只需实例化对象,即都邑指向
原型形式的实行流程:
1.先查找组织函数实例里的属性或要领,假如有,马上返回;
2.假如组织函数实例里没有,则去它的原型对象里找,假如有,就返回。
怎样推断属性时组织函数的实例里,照样原型里?能够运用hasOwnProperty()函数来考证:
console.log(box1.hasOwnProperty('name'));//假如实例里有返回true,不然返回false
怎样推断属性是原型里的?
function Box(){
}
Box.prototype.name="Lee"; //原型属性
Box.prototype.age=100;
Box.prototype.run=function(){ //原型要领
return this.name+this.age+"运转中...";
}
function isProperty(object,property){
return !object.hasOwnProperty(property) && (property in object);
}
var box1=new Box();
console.log(isProperty(box1,'name'));
为了让属性和要领更好的表现封装的结果,而且削减不必要的输入,原型的建立能够运用字面量的体式格局
运用字面量的体式格局建立原型对象,这里的{}就是对象,是object,new Object就相称于{}
function Box(){}
Box.prototype={
name:'Lee',
age:100,
run:function(){
return this.name+this.age+"运转中...";
}
}
var box = new Box();
console.log(box.constructor == Box); //false
字面量建立的体式格局运用constructor属性不会指向实例,而会指向Object,组织函数建立的体式格局则相反。
这里的Box.prototype={}就相称于建立了一个新的对象,所以 box.constructor是Object。
怎样让box.constructor指向Box呢?
function Box(){}
Box.prototype={
constructor:Box,//直接强迫指向即可
name:'Lee',
age:100,
run:function(){
return this.name+this.age+"运转中...";
}
}
var box = new Box();
console.log(box.constructor == Box); //true
重写原型,不会保存之前原型的任何信息,把本来的原型对象和组织函数对象的实例切断了。
function Box(){}
Box.prototype={
constructor:Box,
name:'Lee',
age:100,
run:function(){
return this.name+this.age+"运转中...";
}
}
//重写原型
Box.prototype={
age:200
}
var box = new Box();
console.log(box.name); //undefined
检察sort是不是是Array原型对象里的要领
alert(Array.prototype.sort);
在以下 推断String原型对象里是不是有substring要领
alert(String.prototype.substring);
给String 增加addstring要领:
String.prototype.addstring=function(){
return this+',被增加了!';
}
var box="Lee";
console.log(box.addstring());
注:原型形式建立对象也有本身的瑕玷,它省略了组织函数传参初始化这一历程,带来的瑕玷就是初始化的值都是一致的。而原型最大的瑕玷就是它最大的长处,那就是同享。
原型中所有属性是被许多实例同享的,同享关于函数异常适宜,关于包括基础值的属性也还能够。但假如属性包括援用范例,就存在肯定的题目:
function Box(){}
Box.prototype={
constructor:Box,
name:'Lee',
age:100,
family:['哥哥','姐姐','mm'],
run:function(){
return this.name+this.age+"运转中...";
}
};
var box1 = new Box();
console.log(box1.family); //'哥哥','姐姐','mm'
box1.family.push("弟弟");
console.log(box1.family);//'哥哥','姐姐','mm','弟弟'
var box2 = new Box();
console.log(box2.family);//'哥哥','姐姐','mm','弟弟'
从上面代码能够看出,在第一个实例修改后援用范例,坚持了同享。box2.family同享了box1增加后的援用范例的原型。
为了处理组织传参和同享题目,能够组合组织函数+原型形式:
function Box(name,age){ //坚持自力的用组织函数
this.name=name;
this.age=age;
this.family=['哥哥','姐姐','mm'];
}
Box.prototype={ //坚持同享的用原型
constructor:Box,
run:function(){
return this.name+this.age+"运转中...";
}
}
var box1 = new Box('Lee',100);
console.log(box1.family); //'哥哥','姐姐','mm'
box1.family.push("弟弟");
console.log(box1.family);//'哥哥','姐姐','mm','弟弟'
var box2 = new Box('Jack',200);
console.log(box2.family); //'哥哥','姐姐','mm' //援用范例没有运用原型,所以没有同享
动态原型形式
//把原型封装到组织函数里
function Box(name,age){
this.name=name;
this.age=age;
this.family=['哥哥','姐姐','mm'];
console.log('原型初始化最先'); //实行了两次
Box.prototype.run=function(){
return this.name+this.age+"运转中...";
}
console.log('原型初始化完毕'); //实行了两次
}
//原型的初始化,只需第一次初始化就能够了,没必要每次组织函数实例化的时刻都初始化
var box1 = new Box('Lee',100);
var box2 = new Box('Jack',200);
为了只让第一次初始化,那末就推断
function Box(name,age){
this.name=name;
this.age=age;
this.family=['哥哥','姐姐','mm'];
if(typeof this.run!='function'){
console.log('原型初始化最先'); //实行了一次次
Box.prototype.run=function(){
return this.name+this.age+"运转中...";
};
console.log('原型初始化完毕'); //实行了一次
}
}
//原型的初始化,只需第一次初始化就能够了,没必要每次组织函数实例化的时刻都初始化
var box1 = new Box('Lee',100);
var box2 = new Box('Jack',200);
寄生组织函数
假如以上都不能满足需要,能够运用一下寄生组织函数。
寄生组织函数=工场形式+组织函数
function Box(name,age){
var obj = new Object();
obj.name=name;
obj.age=age;
obj.run=function(){
return this.name+this.age+"运转中...";
}
return obj;
}
var box1 = new Box('Lee',100);
var box2 = new Box('Jack',200);
稳妥组织函数
在一些平安的环境中,比方制止运用this和new,这里的this是组织函数里不运用的this,这里的new是在外部实例化组织函数时不运用new。这类建立体式格局叫做稳妥组织函数。
function Box(name,age){
var obj = new Object();
obj.name=name;
obj.age=age;
obj.run=function(){
return this.name+this.age+"运转中...";
}
return obj;
}
var box1 = Box('Lee',100);
var box2 = Box('Jack',200);
继续
继续是面向对象中一个比较中心的观点。别的正统面向对象言语都邑用两种体式格局完成继续:一个是接口完成,一个是继续。而ECMAScript只支撑继续,不支撑接口完成,而完成继续的体式格局依托原型链完成。
function Box(){
this.name="Lee";
}
function Jack(){
this.age=100;
}
Jack.prototype = new Box();
var jack = new Jack();
console.log(jack.name); //Lee
为了处理援用同享和超范例没法传参的题目,我们采纳一种叫借用组织函数的手艺,或许成为对象假装(捏造对象、典范继续)的手艺处理这两个题目。
function Box(name){
this.name=name;
}
Box.prototype.age=200;
function Jack(name){
Box.call(this,name);
}
var jack = new Jack('Lee');
console.log(jack.name);//Lee
console.log(jack.age);//undefined
然则上面的代码能够看出,对象假装没有继续原型链上的age属性。所以要继续Box的原型,就出现下面的组合继续。
组合继续等于原型链+借用组织函数的形式
function Box(name){
this.name=name;
}
Box.prototype.age=200;
function Jack(name){
Box.call(this,name);
}
Jack.prototype = new Box();
var jack = new Jack('Lee');
console.log(jack.name);//Lee
console.log(jack.age);//200
原型式继续
//暂时中转函数
function obj(o){
function F(){};
F.prototype = o;
return new F();
}
//这是字面量的声明体式格局,相称于var box = new Box();
var box={
name:'Lee',
age:100,
family:['哥哥','姐姐','mm']
};
var box1 = obj(box);
console.log(box1.family);//'哥哥','姐姐','mm'
box1.family.push('弟弟');
console.log(box1.family);//'哥哥','姐姐','mm','弟弟'
var box2 = obj(box);
console.log(box2.family);//'哥哥','姐姐','mm','弟弟'
存在的题目就是援用范例同享了。
寄生式继续
把原型式与工场形式结合起来。
//暂时中转函数
function obj(o){
function F(){};
F.prototype = o;
return new F();
}
//寄生函数
function create(o){
var f=obj(o);
f.run=function(){
return this.name+"要领";
}
return f;
}
//这是字面量的声明体式格局,相称于var box = new Box();
var box={
name:'Lee',
age:100,
family:['哥哥','姐姐','mm']
};
var box1 = create(box);
console.log(box1.run());
寄生组合继续
//暂时中转函数
function obj(o){
function F(){};
F.prototype = o;
return new F();
}
//寄生函数
function create(box,desk){
var f=obj(box.prototype);
f.constructor=desk; //调解原型组织指针
desk.prototype=f;
}
function Box(name,age){
this.name=name;
this.age=age;
}
Box.prototype.run=function(){
return this.name+this.age+"运转中...";
}
function Desk(name,age){
Box.call(this,name,age); //对象假装
}
//经由历程寄生组合继续来完成继续
create(Box,Desk); //这句话用来替换Desk.prototype = new Box();
var desk = new Desk('Lee',100);
console.log(desk.run());