您的位置:首页 > Web前端 > JavaScript

【js基础】javascript中的原型总结

2017-07-26 23:03 656 查看
前言:学习js有段时间,感觉写代码时,很少用到。看懂了过段时间又忘记了。网上关于js原型链和闭包资料满天飞,可见他们的重要性吧。暑假在家看完javascrit高级程序设计第六章,现在做一个笔记,不然估计过几天又忘记了。希望熟悉之后,以后有意识的用一下这些特性。我对于原型的理解都是基于c语言指针和内存知识类比的,可以作为参考,但不保证正确。

这篇博客new出来的对象全部称为对象实例 用于创建对象实例的函数全部称为构造函数 构造函数的原型称为原型对象。

不像java,js中没有类这样显示的定义。所以对象实例的创建都通过函数的封装。看下面栗子:

创建对象实例方法一:工厂模式

function Person(name,age,sex){
var o=new Object();
o.name=name;
o.age=age;
o.sex=sex;
o.sayContent=function(){
alert("hello world");
};
return o;
}
var person1=Person("Tom",18,"男");


这种模式虽然解决了创建多个相似对象问题,却没有解决对象类型问题。主要是这样创建的对象示例无法用js中的对象类型检测手段检测。即

alert(typeof person1);//object
alert(person1 instanceof Person);//false
alert(person1.constructor==Person);//false


而且工厂模式创建对象,很明显是通过函数的显现调用手段进行的。过程如下,在执行var person1=Person(“Tom”,18,”男”);语句时,调用Peson函数,执行Person函数时,先创建一块和Object对象所占内存一样大的内存,然后变量o执行创建这一块内存的地址。o即为这一块内存的地址。然后在这块内存中加入name,age,sex等对象属性值。然后返回对象o的值给person1,即person1的值为创建的那一块内存的地址。最后销毁o的值。但分配的内存不会被销毁。只有当js的垃圾回收机制检测到这一块内存没有用时才会自动释放。

创建对象实例方法二:构造函数模式

构造函数模式克服工厂模式中不能检测创建对象实例的类型问题。

function Person(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
this.sayContent=function(){
alert("hello world");
};
}
var person2=new Person("Jerry",18,"女");
var person3=new Person("Nary",15,"女");
alert(person2 instanceof Person);//true
alert(person2.constructor==Person);//true


构造函数在创建一个对象实例时,先创建一块和构造函数 一样大的内存。然后再调用构造函数,在此过程中this指向该构造函数的实例。即this指向新对象实例。然后执行构造函数里面的代码。其中通过this来向创建的内存中加入新的属性。

但构造函数模式也有缺点:如上例每个对象实例创建时都要分配一块内存,这是无可厚非的,但是在创建每一个对象实例的过程中会调用构造函数Person,在执行构造函数里面的代码

this.sayContent=function(){
alert("hello world");
};
等价于
this.sayContent= new Function(
alert("hello world");
);


时,每一个对象实例在添加sayConntent属性时又要再分配一块小内存,但是这些内存中的内容却一样。可以验证:

alert(person2.sayContent===person3.sayContent);//false


这样很浪费资源。

所以我们可以这样做:

function Person(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
this.sayContent=SayContent;
}
function SayConttent(){
alert("hello world");
}
var person2=new Person("Jerry",18,"女");
var person3=new Person("Nary",15,"女");
alert(person2 instanceof Person);//true
alert(person2.constructor==Person);//true


这样的话,每个对象实例的属性sayContent都执行函数function sayContent的地址。可以验证

alert(person2.sayContent===person3.sayContent);//true


但是这样做又破坏我们封装构造函数来创建对象实例的初衷。

所以原型模式登场。。。原型出来啦。。。。。。。。

创建对象实例方法三:原型模式

function Person(){
}
Person.prototype.age=18;
Person.prototype.sex="男";
Person.prototype.saycontent=function(){
alert("Hello World");
};

var person2=new Person();
var person3=new Person();


先上原理图:



解释:每当我们创建一个构造函数时,这个构造函数都会默认取得一个新的属性prototype,这个属性本质上是一个指针,指向函数的原型对象。。默认状态下,每个原型对象都取得一个默认属性constructor,其本质上也是一个指针,constructor指向prototype属性所在的函数(不一定指向创建的函数,当创建的函数的prototype属性被重写,就不指向创建的函数)。而由构造函数创建的对象实例都会默认取得一个 [b]___proto___ 属性,他本质上也是一个指针,他指向构造函数的原型对象,不指向构造函数。[/b]

function Person(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
}
Person.prototype.sayContent=function(){
alert("hello world");
}
var person2=new Person("Jerry",18,"女");
var person3=new Person("Nary",15,"女");
alert(person2.sayContent==person3.sayContent);//true


多个对象公用一个属性sayContent。上面其实为构造函数模式与原型模式混搭。这种方案在创建js对象实例时用得最多。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript 原型