Javascript 在原型中使用闭包使方法私有
我在我们的项目中使用prototype 1.4,我用这种方式创建类: 1) 举止1 但是,在上面的代码中,可以在外部调用Person“\u check”方法,这不是我所期望的 在我的《感谢T.J.Crowder》一书中,他告诉我一个让方法完全私有化的解决方案: 2) 举止2 现在,“检查”不能暴露在外面 但我现在感到困惑的是,这种方式会导致性能问题还是最好的做法 因为我们创建类(蓝图)的原因之一是为了减少可以在任何地方多次重用的重复代码 现在看看“举止1”: 我们创建一个类Person,然后将所有实例方法放到类Person的原型对象中。 然后每次我们打电话给Javascript 在原型中使用闭包使方法私有,javascript,closures,prototype-programming,Javascript,Closures,Prototype Programming,我在我们的项目中使用prototype 1.4,我用这种方式创建类: 1) 举止1 但是,在上面的代码中,可以在外部调用Person“\u check”方法,这不是我所期望的 在我的《感谢T.J.Crowder》一书中,他告诉我一个让方法完全私有化的解决方案: 2) 举止2 现在,“检查”不能暴露在外面 但我现在感到困惑的是,这种方式会导致性能问题还是最好的做法 因为我们创建类(蓝图)的原因之一是为了减少可以在任何地方多次重用的重复代码 现在看看“举止1”: 我们创建一个类Person,然后将所
var obj=new Person('xx',21);
对象“obj”将拥有Person.prototype中的方法。“obj”本身不包含任何代码
但在“方式2”中:
每次我们打电话:
var obj=new Person('xx',21);
将创建一个新的蓝图,每次还将创建诸如“\u check”之类的私有方法。
这是浪费记忆吗
注意:也许我错了。但我真的很困惑。有人能给我解释一下吗
将创建一个新的蓝图,每次还将创建诸如“\u check”之类的私有方法。这是浪费记忆吗
你错了。在第二种方法中,您只执行周围函数一次,然后将person\u real
分配给person
。代码与第一种方式完全相同(当然除了形式\u检查)。考虑第一种方式的变化:
var Person=Class.create();
Person.prototype={
initialize:function(name,age){
_check(name,age);
this.name=name;
this.age=age;
},
say:function(){
console.log(this.name+','+this.age);
}
}
function _check(name,age){
//....the check code here
}
你还会说每次你打电话给新的人时都会创建检查吗?可能不会。这里的区别在于,\u check
是全局的,可以从任何其他代码访问。通过将此片段放入函数中并立即调用该函数,我们使该函数的\u check
成为本地函数
方法initialize
和say
可以访问\u check
,因为它们是闭包
当我们用普通函数调用替换立即函数时,可能对您更有意义:
function getPersonClass(){
var person_real=Class.create();
person_real.prototype={
initialize:function(name,age){
_check(name,age);
this.name=name;
this.age=age;
},
say:function(){
console.log(this.name+','+this.age);
}
}
//some private method
function _check(name,age){
//....the check code here
}
return person_real;
}
var Person = getPersonClass();
getPersonClass
只调用一次。由于\u check
是在这个函数中创建的,这意味着它也只创建一次。你会发现人们在使用Javascript时遇到一些常见的问题
首先是第二个问题,因为它更容易回答。对于原型继承,您只描述两个相关对象之间的差异。如果在对象的原型上创建一个函数,然后对其进行10000个克隆,那么仍然只有一个函数。每个单独的对象将调用该方法,并且由于Javascript中“this”的工作方式,这些函数调用中的“this”将指向单独的对象,尽管函数存在于单个原型中
当然,当您具有唯一的每项属性、每个对象的唯一值时,您就可以解决性能问题(我不太愿意使用术语“实例”,因为与基于类的继承相比,它在原型继承中的含义并不相同)。由于您不再从单个共享函数/数据集中受益,因此您将失去该好处。了解如何最大限度地降低这些低效率是Javascript(以及任何基于原型继承的语言)智能、高效编程的关键部分。有很多不明显的技巧可以让功能和数据以最小的重复共享
第一个问题是Javascript中常见的一类混淆,因为Javascript中几乎无所不能的功能。Javascript中的函数单独完成其他语言中许多不同结构的工作。类似地,Javascript中的对象在其他语言中扮演着许多数据构造的角色。这种集中的职责为这个表带来了许多强大的选项,但使Javascript成为了一种不折不扣的工具:它看起来非常简单,而且非常简单。但这真的很简单,就像扑克真的很简单一样。这只是一小部分移动的片段,但它们的交互方式产生了一个更深层次的元游戏,很快变得令人困惑
最好将Javascript应用程序/脚本/任何东西中的对象/函数/数据理解为一个不断发展的系统,因为这有助于更好地捕获原型继承。也许就像一场橄榄球(美国)比赛,如果不知道有多少次失败、还有多少次超时、你在哪个季度等等,就无法真正捕捉到比赛的当前状态。你必须随着代码移动,而不是像大多数语言一样看它,甚至像php这样的动态语言
在第一个示例中,基本上您所做的就是使用Class.create自动调用initialize()
函数,并自动处理祖辈构造函数的内容,否则类似于:
var Person = function(){ this.initialize.call(this, arguments) };
Person.prototype = { ... }
没有祖父母的东西。直接在对象上设置的任何属性都将是公共的(除非您使用ES5 defineProperty stuff来专门控制它),因此在名称的开头添加\uu
不会做任何超出约定的事情。javascript中没有私有或受保护的成员。只有公共属性,因此,如果在对象上定义属性,则该属性是公共的。(再次打折ES5,它确实增加了一些控制,但它并不是真正设计用来填充其他语言中的私有变量,不应该以同样的方式使用或依赖它)
我们必须使用作用域来创建隐私,而不是私有成员。记住Javascript只有函数作用域是很重要的如果您想在对象中拥有私有成员,那么您需要将整个对象包装在更大的范围(函数)中,并有选择地公开
function getPersonClass(){
var person_real=Class.create();
person_real.prototype={
initialize:function(name,age){
_check(name,age);
this.name=name;
this.age=age;
},
say:function(){
console.log(this.name+','+this.age);
}
}
//some private method
function _check(name,age){
//....the check code here
}
return person_real;
}
var Person = getPersonClass();
var Person = function(){ this.initialize.call(this, arguments) };
Person.prototype = { ... }