<script >
1.创建一个对象,基本方法
var obj=new Objiect();
obj.name=name;
obj.run=function run () {
return obj.name;
}
这种方法如果还要创建类似的对象,就要重写上面的过程,代码重复写了
所以用工厂模式
2,工厂模式
function createObject () {
var obj=new Object();
obj.name=name;
obj.run=function run () {
return obj.name;
}
return obj;
}
这种办法解决了第一种的缺点,但是,创建出来的对象,无法识别,都是object,
所以有了构造函数穿件对象
3.构造函数创建对象
function Box () {
this.name=name;
this.age=age;
this.run=function run () {
return this.name+this.age;
}
其中的this指向创建出来的新的对象实例
这里没有new Object,为什么可以实例化Box()呢
它的过程如下:
1.首先当使用new构造函数,后台自动 new Objeck();
2,讲构造函数的作用域给新对象,而函数体内的this指向new Object()出来的对象,
3,执行函数体内的代码,
4,后台直接返回新对象
构造函数必修用new运算符调用,谨记
构造函数法创建的对象,每次都要为新对象在栈和堆中分配新的内存空间,特别是堆中的内存空间。如果大了创建对象,系统性能下降厉害
是否可以找到办法,使堆中的对象共同属性不被重复创建,而只是在栈中存在它的引用地址呢?
有,这就出现了原型概念
4.通过原型创建对象,
原型是个对象,它里面的属性和方法,被实例化的对象共享。
改变实例中的原型属性,对原型本来的属性没有影响。(即对其他实例的从原型中获得的属性没有影响)
原型中的属性和方法只能通过修改原型本身修改,也就是重写原型
原型创建的对象,被实例化后,不同的实例之间,原型指向相同的位置,而不只是引用。即在不同的实力的原型,在堆中只有一个位置。
function Box () {
this.name=name;
this.age=age;
this.run=function run () {
return this.name+this.age;
}
Box.prototype.sum=function sum () {
return this.age+this.name+'nihao'
}
或者
Box.prototype={
sum:function sum () {
return this.age+this.name+'nihao'
}
}
原型链,就是原型共享遵循的规则
1.先在实例的构造函数里找,有就返回
2,如果构造函数里没有,则去他的第一级原型里找,有就返回,没有继续向下一级原型中找,知道找到为止,如果都没有,就返回undefiend,
3。所有对象的原型最后都能指向Object()的原型,即null(里面什么也么有)
4.Object()相当于空白对象
function Box () {
}
Box.prototype.sum=function sum () {
return this.age+this.name+'nihao'
}
Box.prototype.name=name;
Box.prototype.age=18;
Box.prototype.time=12;
var box1= new Box()
box1.time=15
alert(box1.time) /15
var box2= new Box()
alert(box2.time) /12
我们可以通过实例访问保存原型中的属性和方法,但不能通过实例重写原型中的值
那么怎么判断这个属性,是构造函数的实例中,还是原型中的属性呢
我们可以用hasOwnProterpy()函数
语法:box.hasOwnProperty('name') /box实例中是否有属性'name'
有返回true,没有返回flase.
我们还可以用:
'name' in box;
来判断属性是否在实例和原型中
如果只在一个中,或者2个中都在,返回true,
一个都在在,则返回false;
有了上面的检测办法,我们可以写出 检测属性在原型中 的方法
function isProperty (object property) {
return !object.hasOwnProperty('property')&&'property'in object
};
var box= new Box()
alert(isProperty(box,name)) /true
通过原型创建的对象,1,它不能传参数,所以创建的初始值都一样,实际意义不大,
而且他的最大优点共享,也是个最大的缺点,因为修改一个实例从原型中获得的属性值,就相当于修改了原型中的属性值,导致其他后面实例化得值也会修改
这样我们就需要一种这样的方法,初始化需要得到不同值的属性和方法能得到不同的值,而不需要不同值得属性和方法,可以得到一样的属性和方法。有没有这样的方法呢?
有
5.构造函数+原型模式创建 对象
function Box (user,age) {
this.user=user;
this.age=age;
}
Box.prototype={
info:'dajiahao'
run:function run () {
return 'sb'
}
}
var box1=new Box('le',11)
alert(box1.name)
var box2=new Box('ta',22)
alert(box2.name)
这种方法很怪异,最好把构造函数和原型封装到一起
而且,每次调用原型中的方法,都会初始化原型中的方法
所以有了改进方法
6.动态原型模式 (我们一般用这种办法)
function Box (user,age) {
this.user=user;
this.age=age;
if (!typeof this.run='function') {
Box.prototype.run=function run () {
return 'sb'
}
};
}
7.特殊的创建原型的方法
1.寄生构造函数
其实就是工厂模式+构造函数
它解决了这样一个问题,JS中的内置对象,如果想创建新的方法,可以用他,如果用上面的原型模式+构造函数创建,例如String.prototype.add(),
会引起其他string的不便和混乱
function myString (string) {
var str=new String(string)
str.addstring=function () {
return this+",被添加了"
}
return str
}
var box= new myString('lee')
alert(box.addstring());
给要真正执行的函数套个函数壳子,巧妙
继承
1.通过原型链继承
function Box () {
this.fimily=[1,2,3,4]
}
function Desk () {
}
Desk.prototype=new Box();
var a=new Desk();
alert(a.fimily)
上面有上面缺点呢,
1.如果重写a的原型(即通过实例修改原型的值),其他实例通过原型获得属性和方法得值也会被重写
2.写出来的实例初始值都一样,也就是无法传参数改变初始值
2.对象冒充,或者叫经典继承,解决了上面2个缺点,因为他传参数了,所以不用从写原型
function Box (age,name) {
this.name=name;
this.age=age;
this.run=function run (argument) {
return this.age+this.name;
}
}
function Desk (age,name) {
Box.call(this,age,name)
}
var desk=new Desk('lee',18)
alert(desk.run())
这种方法只是借用函数,没有原型,无法复用(即封装起来,给其他对象用)
为了解决复用问题,有了下面方法
原型链+对象冒充模式,(组合继承)
function Box (name,age) {
this.name=name;
this,age=age;
Box.prototype.run=function () {
return this.name + this.age;
}
}
function Desk (name,age) {
Box.apply(this,[name,age])
}
Desk.prototype=new Box();
var desk=Desk('ke',18)
alert(desk.run())
组合继承一般很常用,但有一个问题,就是超类型在使用过程中会被调用2次:一次是创建子类的时候,一次是在子类型构造函数内部对象冒充处。消耗系统性能
为了解决这个问题有了,寄生组合继承
通过一个中转函数,一个寄生函数,实现继承
中转函数
function obj(o) {
function F() {}
F.prototype = o;
return new F();
}
寄生函数
function create(box, desk) {
var f = obj(box.prototype);
f.constructor = desk; /不加这句,desk指向box的原型了
desk.prototype = f;
}
function Box(name) {
this.name = name;
this.arr = ['哥哥','妹妹','父母'];
}
Box.prototype.run = function () {
return this.name;
};
function Desk(name, age) {
Box.call(this, name); //第二次调用Box
this.age = age;
}
// Desk.prototype = new Box(); /这句话被寄生继承替代了
create(Box,Desk)
var desk=new Desk('lee',100)
alert(message)
</script>