面向对象与原型

工厂模式:
有个问题,识别问题,因为根本无法搞清楚他们到底是哪个对象的实例。box1和box2都是属于对象
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',100);
var box2=createObject('Jack',200);

---------------------------------------------------------------------------------------------

构造函数模式
function Box(name,age){ //创建一个对象,所有构造函数的对象其实就是Object
this.name=name; //添加一个属性
this.age=age;
this.run=function(){ //添加一个方法
return this.name+this.age+'运行中...';
};
}

function Desk(name,age){ //创建一个对象,所有构造函数的对象其实就是Object
this.name=name; //添加一个属性
this.age=age;
this.run=function(){ //添加一个方法
return this.name+this.age+'运行中...';
};
}
//1.构造函数没有new Object,但它后台会自动var obj=new Object
//2.this就相当于obj
//3.构造函数不需要返回对象引用

创建的规范:
//1.构造函数也是函数,但函数名第一个字母大写
//2.必须new构造函数名(),new Box(),而这个Box第一个字母也是大写的
//3.必须使用new运算符
var box1=new Box('Lee',100);
var box2=new Box('Jack',100);
var box3=new Desk('kkk',100);
alert(box1.run());
alert(box2.run());

alert(box1 instanceof Box); //true
alert(box2 instanceof Box); //true
alert(box3 instanceof Box); //false 可以识别,因为box3是Desk对象的引用

-------------------------------------
function Box(name,age){
this.name=name;
this.age=age;
this.run=function(){
return this.name+this.age+'运行中...';
};
}
var box1=new Box('Lee',100); //实例化后地址为1
var box2=new Box('Lee',100); //实例化后地址为2
alert(box1.run==box2.run); //false 因为是引用类型
-------------------------------------
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);
var box2=new Box('Lee',100);
alert(box1.run==box2.run); //true

-------------------------------------------------------------------------------------------------
原型:

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();
alert(box1.run==box2.run); //true
alert(box1.__proto__); //[object Object] 这个属性是一个指针指向prototype原型对象
alert(box1.constructor); //构造属性,可以获取构造函数本身
//作用是被原型指针定位,然后得到的构造函数本身
//其实就是对象实例对应的原型对象的作用


isPrototypeOf

判断一个对象实例(对象引用)是不是指向了对象的原型对象
alert(Box.isPrototypeOf(box1));

function Box(){} //构造函数函数体内什么都没有,这里如果有,叫做实例属性,实例方法

Box.prototype.name='Lee';
Box.prototype.age=100;
Box.prototype.run=function(){
return this.name+this.age+'运行中...';
}
var box1=new Box();
//alert(Box.prototype.isPrototypeOf(box1)); //true


var obj=new Object();
alert(Object.prototype.isPrototypeOf(box1)); //true

delete box1.name; //删除实例中的属性
delete Box.prototype.name; //删除原型中的属性
Box.prototype.name='kkk'; //覆盖原型中的属性


---------------------------------------------------
hasOwnProperty


function Box(){} //构造函数函数体内什么都没有,这里如果有,叫做实例属性,实例方法

Box.prototype.name='Lee';
Box.prototype.age=100;
Box.prototype.run=function(){
return this.name+this.age+'运行中...';
}
var box1=new Box();
box1.name='Kac';
alert(box1.hasOwnProperty('name')); //true 判断实例中是否存在指定属性
--------------------------------------------------------
in

function Box(){} //构造函数函数体内什么都没有,这里如果有,叫做实例属性,实例方法

Box.prototype.name='Lee';
Box.prototype.age=100;
Box.prototype.run=function(){
return this.name+this.age+'运行中...';
}
var box1=new Box();
alert('name' in box1); //true 不管实例属性或原型属性是否存在,只要有就返回true,两边都没有,返回false

--------------------------------------------------------
判断只有原型中有属性:

function isProperty(object,property){ //object 是实例对象 property是属性
return !object.hasOwnProperty(property)&&(property in object)
}

--------------------------------------------------------
区别:

function Box(){}

Box.prototype.name='Lee';
Box.prototype.age=100;
Box.prototype.run=function(){
return this.name+this.age+'运行中...';
}
var box1=new Box();
alert(box1.constructor); //function Box(){}


function Box(){}

Box.prototype={
name:'Lee',
age:100,
run:function(){
return this.name+this.age+'运行中...';
}
};
var box=new Box();
alert(box.constructor); //function Object() { [native code] }
-------------------------------------
function Box(){}

Box.prototype={
constructor: Box, //强制指向Box
name:'Lee',
age:100,
run:function(){
return this.name+this.age+'运行中...';
}
};
var box=new Box();
alert(box.constructor); //function Box(){}

--------------------------------------------------------------------

function Box(){}

Box.prototype={
constructor: Box, //强制指向Box
name:'Lee',
age:100,
run:function(){
return this.name+this.age+'运行中...';
}
};

//重写了原型对象

Box.prototype={
age:20 //这里不会保留之前原型的任何信息了
};

var box=new Box();
alert(box.name); //undefined

--------------------------------------------------------------------

alert(Array.prototype.sort);

--------------------------------------------------------------------
//内置引用类型的功能扩展
String.prototype.addstring=function(){
return this+',被添加了!';
}
var box='Lee';
alert(box.addstring());

//ps:尽管给原生的内置引用类型添加方法使用起来特别方便,但我们不推荐使用这种方法。因为它可能会导致命名冲突,不利于代码维护。
--------------------------------------------------------------------
//原型的缺点

function Box(){}

Box.prototype={
constructor:Box,
name:'Lee',
age:100,
family:['哥哥','姐姐','妹妹'],
run:function(){
return this.name+this.age+'运行中...'
}
}

var box1=new Box();
alert(box1.family);
box1.family.push('弟弟');
alert(box1.family);

var box2=new Box();
alert(box2.family);

--------------------------------------------------------------------

//组合构造函数+原型模式
function Box(name,age){ //保持独立的用构造函数
this.name=name;
this.age=age;
this.family=['哥哥','姐姐','妹妹'];
}

Box.prototype={
constructor:Box,
run:function(){
return this.name+this.age+'运行中...'
}
}

var box1=new Box('Lee',100);
alert(box1.run());
var box2=new Box('Jack',200);
alert(box2.run());

--------------------------------------------------------------------
动态原型模式:

function Box(name,age){ //保持独立的用构造函数
this.name=name;
this.age=age;
this.family=['哥哥','姐姐','妹妹'];
Box.prototype.run=function(){
return this.name+this.age+'运行中...'
}
}

var box1=new Box('Lee',100);
var box2=new Box('Jack',200);

//原型的初始化,只要第一次初始化,就可以了,没必要每次构造函数实例化的时候都初始化

所以,看下面:

function Box(name,age){ //保持独立的用构造函数
this.name=name;
this.age=age;
this.family=['哥哥','姐姐','妹妹'];
if(typeof this.run!='function'){ //判断this.run是否存在
Box.prototype.run=function(){
return this.name+this.age+'运行中...'
}
}
}

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);
alert(box1.run());
var box2=new Box('Jack',200);
alert(box2.run());

--------------------------------------------------------------------
稳妥构造函数:构造函数中不使用this和实例化不使用new

function Box(){
var obj=new Object();
obj.name=name;
obj.age=age;
obj.run=function(){
return name+age+'运行中...'
}
return obj;
}

var box1=Box('Lee',100);
alert(box1.run());
var box2=Box('Jack',200);
alert(box2.run());


----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
继承,通过原型链实现

function Box(){ //被继承的函数叫做超类型(父类,基类)
this.name='Lee';
}
function Desk(){ //继承的函数叫做子类型(子类,派生类)
this.age=100;
}
//通过原型链继承,超类型实例化后的对象实例,赋值给子类型的原型属性
//new Box()会将Box构造里的信息和原型里的信息都交给Desk
Desk.prototype=new Box();

var desk=new Desk();
alert(desk.name);


--------------------------------------------------------------
使用对象冒充继承

function Box(name,age){
this.name=name;
this.age=age;
//this.family=['哥哥','姐姐','妹妹']; //不会被共享
}

Box.prototype.family='家庭';

function Desk(name,age){
Box.call(this,name,age); //对象冒充
}

var desk=new Desk('Lee',100);
alert(desk.name);
alert(desk.family); //对象冒充,只能继承构造里的信息,原型里的继承不了

--------------------------------------------------------------

function Box(name,age){
this.name=name;
this.age=age;
this.family=['哥哥','姐姐','妹妹'];
}
Box.prototype.run=function(){
return this.name+this.age+'运行中...';
}
//构造函数里的方法,放在构造里,每次实例化,都会分配一个内存地址,浪费,所以最好放在原型里

function Desk(anme,age){
Box.call(this,name,age);
}
var desk=new Desk('Lee',100);
alert(desk.run()); //desk.run is not a function

--------------------------------------------------------------
组合继承: 对象冒充+原型链 重点,用的比较广泛

function Box(name,age){
this.name=name;
this.age=age;
this.family=['哥哥','姐姐','妹妹'];
}
Box.prototype.run=function(){
return this.name+this.age+'运行中...';
}

function Desk(anme,age){
Box.call(this,name,age); //对象冒充
}

Desk.prototype=new Box(); //原型链继承

var desk=new Desk('Lee',100);
alert(desk.run());

--------------------------------------------------------------------------------------------------------

之前讲的继承:1.原型链继承,2.借用构造函数继承(对象冒充继承) 3.组合继承(结合前两种)


4.原型式继承

 

posted @ 2017-07-31 09:54  耿鑫  阅读(106)  评论(0编辑  收藏  举报