本文的目标是让人人明白什么状况下把函数的要领写在JavaScript的组织函数上,什么时刻把要领写在函数的
prototype
属性上;以及如许做的优点.
为了浏览轻易,我们商定一下:把要领写在组织函数内的状况我们简称为函数内要领,把要领写在prototype
属性上的状况我们简称为prototype上的要领
起首我们先相识一下这篇文章的重点:
函数内的要领: 运用函数内的要领我们能够接见到函数内部的私有变量,假如我们经由过程组织函数
new
出来的对象须要我们操纵组织函数内部的私有变量的话,
我们这个时刻就要斟酌运用函数内的要领.prototype上的要领: 当我们须要经由过程一个函数建立大批的对象,而且这些对象还都有许多的要领的时刻;这时候我们就要斟酌在函数的
prototype
上增加这些要领.
这类状况下我们代码的内存占用就比较小.在现实的运用中,这两种要领往往是连系运用的;所以我们要起首相识我们须要的是什么,然后再去挑选怎样运用.
我们照样依据下面的代码来申明一下这些要点吧,下面是代码部份:
// 组织函数A
function A(name) {
this.name = name || 'a';
this.sayHello = function() {
console.log('Hello, my name is: ' + this.name);
}
}
// 组织函数B
function B(name) {
this.name = name || 'b';
}
B.prototype.sayHello = function() {
console.log('Hello, my name is: ' + this.name);
};
var a1 = new A('a1');
var a2 = new A('a2');
a1.sayHello();
a2.sayHello();
var b1 = new B('b1');
var b2 = new B('b2');
b1.sayHello();
b2.sayHello();
我们起首写了两个组织函数,第一个是A
,这个组织函数内里包含了一个要领sayHello
;第二个是组织函数B
,我们把谁人要领sayHello
写在了组织函数B
的prototype
属性上面.
须要指出的是,经由过程这两个组织函数new
出来的对象具有一样的属性和要领,然则它们的区分我们能够经由过程下面的一个图来申明:
我们经由过程运用组织函数A
建立了两个对象,分别是a1
,a2
;经由过程组织函数B
建立了两个对象b1
,b2
;我们能够发明b1
,b2
这两个对象的谁人sayHello
要领都是指向了它们的组织函数的prototype
属性的sayHello
要领.而a1
,a2
都是在本身内部定义了这个要领.
定义在组织函数内部的要领,会在它的每一个实例上都克隆这个要领;定义在组织函数的prototype
属性上的要领会让它的一切示例都同享这个要领,然则不会在每一个实例的内部从新定义这个要领.假如我们的运用须要建立许多新的对象,而且这些对象另有许多的要领,为了节约内存,我们发起把这些要领都定义在组织函数的prototype
属性上固然,在某些状况下,我们须要将某些要领定义在组织函数中,这类状况平常是由于我们须要接见组织函数内部的私有变量.
下面我们举一个二者连系的例子,代码以下:
function Person(name, family) {
this.name = name;
this.family = family;
var records = [{type: "in", amount: 0}];
this.addTransaction = function(trans) {
if(trans.hasOwnProperty("type") && trans.hasOwnProperty("amount")) {
records.push(trans);
}
}
this.balance = function() {
var total = 0;
records.forEach(function(record) {
if(record.type === "in") {
total += record.amount;
}
else {
total -= record.amount;
}
});
return total;
};
};
Person.prototype.getFull = function() {
return this.name + " " + this.family;
};
Person.prototype.getProfile = function() {
return this.getFull() + ", total balance: " + this.balance();
};
在上面的代码中,我们定义了一个Person
组织函数;这个函数有一个内部的私有变量records
,这个变量我们是不愿望经由过程函数内部之外的要领去操纵这个变量,所以我们把操纵这个变量的要领都写在了函数的内部.而把一些能够公然的要领写在了Person
的prototype
属性上,比方要领getFull
和getProfile
.
把要领写在组织函数的内部,增加了经由过程组织函数初始化一个对象的本钱,把要领写在prototype
属性上就有用的减少了这类本钱.你或许会以为,挪用对象上的要领要比挪用它的原型链上的要领快得多,实在并非如许的,假如你的谁人对象上面不是有许多的原型的话,它们的速率现实上是差不多的。
别的,须要注重的一些处所:
起首假如是在函数的
prototype
属性上定义要领的话,要切记一点,假如你转变某个要领,那末由这个组织函数发生的一切对象的谁人要领都会被转变.另有一点就是变量提拔的题目,我们能够轻微的看一下下面的代码:
func1(); // 这里会报错,由于在函数实行的时刻,func1还没有被赋值. error: func1 is not a function var func1 = function() { console.log('func1'); }; func2(); // 这个会被准确实行,由于函数的声明会被提拔. function func2() { console.log('func2'); }
关于对象序列化的题目.定义在函数的
prototype
上的属性不会被序列化,能够看下面的代码:function A(name) { this.name = name; } A.prototype.sayWhat = 'say what...'; var a = new A('dreamapple'); console.log(JSON.stringify(a));
我们能够看到输出结果是
{"name":"dreamapple"}
原文地点:github
参考的文章或许问答: