JavaScript中的原型

构造函数

在JS中,使用构造函数时要注意以下两点:

构造函数用于创建某一类对象,其首字母要大写 构造函数要和new一起使用才有意义

new在执行时会做四件事情:

[1] 在内存中创建一个新的空对象。

[2] 让this指向这个新的对象。

[3] 执行构造函数里面的代码,给这个新对象派加属性和方法。

[4] 返回这个新对象(所以构造函数里面不需要 return)。

实例函数和原型函数的关系图示:

_ _ proto_ _作用:指向构造函数的原型属性constructor

通过这两个属性就可以访问到原型里的属性和方法

 

 

【3】、工厂模式

为了解决多个类似对象声明的问题,我们可以使用一种叫工厂模式的方法,这种方法就是为了解决实例化对象产生大量重复的问题。

function createObject(name,age){

var obj=new Object(); //创建对象

obj.name=name; //添加属性

obj.age=age;

obj.run=function(){ //添加方法

return this.name+this.age+'运行中...';

};

return obj; //返回对象引用

};

【4】、构造函数模式

(可以理解为改良后的工厂化)

function Box(name,age){ //创建一个对象,所有构造函数的对象就是object

this.name=name; //添加一个属性

this.run=function(){

return this.name+this.age+'运行中...';

};

};

function Desk(name,age){ //创建一个对象,所有构造函数的对象就是object

this.name=name; //添加一个属性

this.run=function(){

return this.name+this.age+'运行中...';

};

};

var box1=new Box('Lee',100); //实例化,必须new出Box才能实例化

var box2=new Box('jack',200); //实例化

alert(box1.run);

alert(box2.run);

构造函数方法的一些规范:

1.构造函数也是函数,但函数名第一个字母大写

2.必须使用new关键字构造函数名(),new Box()

3.必须使用new运算符

函数构造与工厂模式的不同:

1.构造函数没有new Object ,但它后台会自动var obj=new Object

2.直接将属性和方法赋值给this对象(this就相当于obj)

3.没有return语句(构造函数不需要返回对象引用,它是后台自动返回的)

构造函数与普通函数的区别:

调用方式不同,构造函数必须使用new运算符来调用

构造函数也是函数,但函数名第一个字母大写

构造函数,用普通函数调用一般是无效的,必须使用new关键字

对象冒充

function Box(name,age){ //创建一个对象,所有构造函数的对象就是object

this.name=name; //添加一个属性

this.run=function(){

return this.name+this.age+'运行中...';

};

};

var o=new Object();

Box.call(o,'Lee',100); //对象冒充

alert(o.run());

var box1=new Box('Lee',100); //实例化后地址为1

var box2=new Box('Jack',200); //实例化后地址为2

alert(box1.name==box2.name); //true

alert(box1.age==box2.age); //true

alert(box1.run()==box2.run()); //true

alert(box1.run==box2.run); //false,因为他们比较的是引用地址

【5】、原型

我们创造的每一个函数都有一个prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法

构造函数中的属性和方法叫做实例属性、实例方法

function Box(name,age){

this.name=name; //实例属性

this.age=age;

this.run=function(){ //实例方法

return this.name+this.age+'运行中...';

};

};

原型

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());

alert(box2.run());

alert(box1.constructor); //构造属性,可以获取构造函数本身

如果是实例方法,不同的实例化,它们的方法地址是不一样的,是唯一的

如果是原型方法,那么它们的地址是共享的,大家都是一样的

alert(box1.run==box2.run); //true

alert(box1.prototype); //这个属性是一个对象,是访问不到的

alert(box1.proto); //这个属性是一个指针,指向prototype原型对象,

判断一个对象实例是否指向了对象的原型对象

alert(Box.prototype.isPrototypeOf(box1)); //只要实例化对象,即都会指向

原型模式的执行流程:

1.先查找构建函数实例里的属性或方法,如果有,立刻返回

2.如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回

function Box(){

this.name='Jack'; // 实例中的属性

};

Box.prototype.name='Lee'; //原型中的属性

var box1=new Box();

var box2=new Box();

alert(box1.name); //Jack

alert(box2.name); //因为实例属性不会共享,只能访问原型属性,原型属性是可以共享的,因此访问到Lee

delete box1.name; //删除实例中的属性

delete Box.prototype.name; //删除原型中的属性,一般不用

Box.prototype.name='kkk'; //覆盖原型中的属性

alert(box1.name);

如何判断属性是否在构造函数的实例里

alert(box.hasOwnProperty('name')); //实例有返回true,否则返回false

只要能访问到就返回true,无论是实例属性还是原型属性

alert('name' in box1);

判断只有原型中有属性

function isProperty(object,property){

return !object.hasOwnProperty(property)&&(property in object);

}

【6】、原型的字面量写法

为了让属性和方法更好地体现封装的效果,并且减少不必要的输入

原型的创建可以使用字面量的方式

function Box(){};

Box.prototype={ //使用字面量的方式创建原型对象,这里的{}就是对象,相当于object,{}表示new object

constructor:Box, //强制指向Box

name:'Lee',

age:100,

run:function(){

return this.name+this.age+'运行中...';

}

};

var box=new Box();

alert(box.name);

重写会带来问题

内置引用类型的功能扩展(不推荐)

String.prototype.addstring=function(){

return this+',被添加了!';

};

var box='Lee';

alert(box.addstring());

【7】、原型的缺点:

1.无法保持独立性

2.共享

3.不能重写,重写就会被覆盖

function Box(){}; Box.prototype={ constructor:Box, name:'Lee', age:20, family:['哥哥','姐姐','弟弟','妹妹'] }; var box=new Box(); box.family.push('妈妈'); //在第一个实例修改后,引用类型保持了共享

alert(box.family);

var box2=new Box();

alert(box2.family); //共享了box1添加后的引用类型的原型

因为共享的原因,很多开发者放弃使用原型

组合构造函数+原型模式

function Box(name,age)={ //保持独立地用构造函数

constructor:Box,

name:'Lee',

age:20,

family:['哥哥','姐姐','弟弟','妹妹']}

Box.prototype={ //保持共享的用原型

constructor:Box,

run:function(){

return this.name+this.age+'运行中...';

}

};

var box1=new Box();

box1.family.push('妈妈');

alert(box1.family);

var box2=new Box();

alert(box2.family); //在第一个实例修改后,引用类型没有使用原型,所以没有共享

【8】动态原型模式

将原型封装到构造函数里

function Box(name,age)={

constructor:Box,

name:'Lee',

age:20,

family:['哥哥','姐姐','弟弟','妹妹']

alert('原型初始化开始');

Box.prototype.run=function{

return this.name+this.age+'运行中...';

}

alert('原型初始化结束');

};

var box1=new Box();

box1.family.push('妈妈');

alert(box1.family);

var box2=new Box();

alert(box2.family);

出现问题:原型初始化多次,会浪费资源,但原型初始化一次即可

解决方法:

将原型封装到构造函数里

function Box(name,age)={

constructor:Box,

name:'Lee',

age:20,

family:['哥哥','姐姐','弟弟','妹妹']

if(typeOf this.run != 'function'){ //仅在第一次调用的时候初始化

alert('原型初始化开始');

Box.prototype.run=function(){

return this.name+this.age+'运行中...';

}

alert('原型初始化结束');

};

};

var box1=new Box();

box1.family.push('妈妈');

alert(box1.family);

var box2=new Box();

alert(box2.family);

当第一次调用的时候,run不存在,当第二次调用,run就存在了,不会再初始化了

【9】寄生构造函数

寄生构造函数=工厂模式+构造函数

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());

【10】稳妥构建函数

在一些安全环境中,比如禁止使用this和new,这里的this是构造函数里不使用this,这里的new是在外部实例化构造函数时不使用new。这种创建方式叫做稳妥构造函数。

function Box(name,age){

var obj=new Object();

obj.name=name;

obj.age=age;

obj.run=function run(){

return this.name+this.age+'运行中...';

};

return obj;

}

var box1=Box('Lee',100);

alert(box1.run());

var box2=Box('Jack',200);

alert(box2.run());

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰镇奶茶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值