Javascript 将原型函数绑定到此函数的不太详细的方式
我使用以下声明类的范例:Javascript 将原型函数绑定到此函数的不太详细的方式,javascript,refactoring,prototype,Javascript,Refactoring,Prototype,我使用以下声明类的范例: var myNamespace = myNamespace || {}; (function () { myNamespace.MyClass = function () { if (!(this instanceof myNamespace.MyClass)) { return new myNamespace.MyClass(); } this.field = 17;
var myNamespace = myNamespace || {};
(function () {
myNamespace.MyClass = function () {
if (!(this instanceof myNamespace.MyClass)) {
return new myNamespace.MyClass();
}
this.field = 17;
this.foo = this.foo.bind(this);
this.bar = this.bar.bind(this);
};
myNamespace.MyClass.prototype.foo = function(){
console.log(this.field + 1);
};
myNamespace.MyClass.prototype.bar = function(){
console.log(this.field + 2);
};
})();
我使用prototype
来避免在每次实例化时重新说明对象方法,并使代码更干净—将类字段与其逻辑分离。我在每个方法上调用
bind
,以避免在这个
指向方法内部错误的地方出现讨厌的bug
它可以工作,但很容易出错——我必须记住对每个方法调用bind
,而且太冗长了,特别是当有两个以上的方法时
是否有更干净的*方法来声明此类函数(绑定到其类型的this
,并在原型上声明)?
*我知道“clean”并没有很好的定义——一个简单的度量就是代码长度 声明类后附加到命名空间:
var myNamespace = myNamespace || {};
(function () {
var MyClass = function () {
this.field = 17;
};
MyClass.prototype.foo = function(){
console.log(this.field + 1);
};
MyClass.prototype.bar = function(){
console.log(this.field + 2);
};
this.MyClass = MyClass;
}).call(myNamespace);
通过以命名空间作为作用域调用IIFE,您可以通过在
this
对象上公开类来保持模块干净。声明类后附加到命名空间:
var myNamespace = myNamespace || {};
(function () {
var MyClass = function () {
this.field = 17;
};
MyClass.prototype.foo = function(){
console.log(this.field + 1);
};
MyClass.prototype.bar = function(){
console.log(this.field + 2);
};
this.MyClass = MyClass;
}).call(myNamespace);
通过使用名称空间作为作用域调用IIFE,您可以通过在
this
对象上公开类来保持模块的干净。您不应该像那样绑定您的方法-您在每个实例上创建新函数,而您实际上应该在原型上使用方法来节省内存。如果您创建100个实例,您将创建200个新函数!这样一种简单的模式更为常见,可以很好地工作:
var myNamespace = myNamespace || {};
myNamespace.MyClass = (function() {
function MyClass() {
this.field = 17;
}
MyClass.prototype = {
constructor: MyClass,
foo: function() {
console.log(this.field + 1);
},
bar: function(){
console.log(this.field + 2);
}
};
return MyClass;
}());
你不应该像那样绑定你的方法——你在每个实例上创建新的函数,而实际上你应该在原型上使用这些方法来节省内存。如果您创建100个实例,您将创建200个新函数!这样一种简单的模式更为常见,可以很好地工作:
var myNamespace = myNamespace || {};
myNamespace.MyClass = (function() {
function MyClass() {
this.field = 17;
}
MyClass.prototype = {
constructor: MyClass,
foo: function() {
console.log(this.field + 1);
},
bar: function(){
console.log(this.field + 2);
}
};
return MyClass;
}());
您可以在单个赋值中压缩一些原型定义,并将名称空间传递到函数调用中
var myNamespace = myNamespace || {};
(function () {
function MyClass() {
this.field = 17;
};
MyClass.prototype = {
foo: function () {
console.log(this.field + 1);
},
bar: function () {
console.log(this.field + 2);
}
};
})(myNamespace);
您可以在单个赋值中压缩一些原型定义,并将名称空间传递到函数调用中
var myNamespace = myNamespace || {};
(function () {
function MyClass() {
this.field = 17;
};
MyClass.prototype = {
foo: function () {
console.log(this.field + 1);
},
bar: function () {
console.log(this.field + 2);
}
};
})(myNamespace);
当您有完全可重用的泛型方法时,绑定是不好的。你可以给函数起一个名字来避免“prototype”。在任何地方,只要将构造函数发布到你的命名空间,并在包装器中使用本地路径就可以了。“我在每个方法上调用bind,以避免讨厌的bug”,这是非常过分的。理解JavaScript的工作原理并有意避免这些错误,比试图“修复”语言、避免整个过程中的一整套功能要好得多。这些讨厌的错误经常发生,特别是如果你像我一样使用knockoutjs。考虑一下所描述的内容。当你的方法用另一个上下文调用时,你应该小心和有见识。最好的解决方案不是在每个实例上都有绑定方法。如果有完全可重用的泛型方法,绑定就不好。你可以给函数起一个名字来避免“prototype”。在任何地方,只要将构造函数发布到你的命名空间,并在包装器中使用本地路径就可以了。“我在每个方法上调用bind,以避免讨厌的bug”,这是非常过分的。理解JavaScript的工作原理并有意避免这些错误,比试图“修复”语言、避免整个过程中的一整套功能要好得多。这些讨厌的错误经常发生,特别是如果你像我一样使用knockoutjs。考虑一下所描述的内容。当你的方法用另一个上下文调用时,你应该小心和有见识。最好的解决方案不是在每个实例上都有绑定方法。假设在其他地方,我实例化:
var asdf=new myNamespace.MyClass()
,然后将asdf.foo
传递给:window.addEventListener(“DOMContentLoaded”,asdf.foo)
,这会指向asdf
?如果不调用bind
,它将如何工作?当您添加事件侦听器时,无论您希望它维护什么范围(或使用匿名函数),您都会调用bind。创建函数时不绑定。假设在其他地方,我实例化:var asdf=new myNamespace.MyClass()
,然后将asdf.foo
传递给:window.addEventListener(“DOMContentLoaded”,asdf.foo)
,这一点会在asdf
吗?如果不调用bind
,它将如何工作?当您添加事件侦听器时,无论您希望它维护什么范围(或使用匿名函数),您都会调用bind。创建函数时没有绑定。请看我在@Jivings的回答中问的问题-此解决方案是否会丢失与实例的绑定?是的,这就是问题所在,您不想这样做。就像我说的,bind创建了一个新函数,所以你在每个实例上创建了两个新函数,它们必须存储在内存中。这是一种低效的、糟糕的做法——事实上,它完全绕过了使用原型的目的。只需使用window.addEventListener(“DOMContentLoaded”,function(){asdf.foo();})代码>。如果您经常这样做,那么将其抽象为一个helper函数。绑定并不意味着是一种可以在每个类方法上使用的通用工具。请看我在@Jivings的回答中提出的问题-这个解决方案是否会丢失对实例的绑定?是的,这就是问题所在,您不想这样做。就像我说的,bind创建了一个新函数,所以你在每个实例上创建了两个新函数,它们必须存储在内存中。这是一种低效的、糟糕的做法——事实上,它完全绕过了使用原型的目的。只需使用window.addEventListener(“DOMContentLoaded”,function(){asdf.foo();})代码>。如果您经常这样做,那么将其抽象为一个helper函数。绑定并不意味着它是一种可以在每个类方法上使用的通用工具。