Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在原型中进行事件绑定是否明智&;为什么失去了这方面的背景?_Javascript_Jquery_Prototype_Jquery Events - Fatal编程技术网

Javascript 在原型中进行事件绑定是否明智&;为什么失去了这方面的背景?

Javascript 在原型中进行事件绑定是否明智&;为什么失去了这方面的背景?,javascript,jquery,prototype,jquery-events,Javascript,Jquery,Prototype,Jquery Events,在为网页创建模块化JavaScript代码时,我通常需要将事件附加到按钮等 以AMD模块中常见的以下示例代码为例: define(function(require) { var MyObject = function(ele) { this.ele = ele; } MyObject.prototype = { myfunct: function() { console.log('myfunct called')

在为网页创建模块化JavaScript代码时,我通常需要将事件附加到按钮等

以AMD模块中常见的以下示例代码为例:

define(function(require) {

    var MyObject = function(ele) {
        this.ele = ele;
    }

    MyObject.prototype = {
        myfunct: function() {
            console.log('myfunct called');
        }
    }

    return MyObject;

});
在本页的稍后部分,我将执行以下操作:

$(document).ready(function() {
    var button = $('#button'),
        myobj = new MyObject(button);

    button.click(function() {
        myobj.myfunct();
    });
});
这是可行的,但我觉得还是有点不干净

例如,我需要在全局命名空间中创建至少一个变量,以将函数绑定到按钮。此外,当一个页面上有许多JavaScript支持的交互时,代码会变得混乱——这是我最初希望通过使用模块化JavaScript来解决的问题

这就是为什么我的想法是将事件绑定到原型中:

var MyObject = function(ele) {
    self = this;
    this.element = ele; 

    this.init();
}

MyObject.prototype = {
    init: function() {        
        $(this.element).click(function() {
           self.myfunct();
        });
    },
    myfunct: function() {
        console.log('myfunct called');
    }
}
这样,模块外部的代码将如下所示:

$(document).ready(function() {
    var button = $('#button'),
        myobj = new MyObject(button);

});
将事件绑定移动到原型中是否明智?如果是这样的话,我这样做可以吗,或者有没有办法使用
init()

此外,我注意到,当页面上有两个按钮时,某些上下文会丢失–
self
始终引用
MyObj
的最后一个实例

为什么会发生这种情况——我用
self=this思考我可以阻止上下文?


让我们从第二个问题开始。代码的问题在于,您将
self
声明为全局变量,因为您忘记/忽略了
var
关键字。因此,当您创建两个或多个实例时,最后一个实例将覆盖上一个实例,并且所有单击事件中的
self
将指向最后一个实例

检查固定代码。请注意,您必须将
var self=this
移动到init方法,因为现在它是局部变量:

var MyObject = function(ele) {
    this.element = ele; 
    this.init();
}

MyObject.prototype = {
    init: function() {        
        var self = this;
        $(this.element).click(function() {
           self.myfunct();
        });
    },
    myfunct: function() {
        console.log('myfunct called');
    }
}

至于第一个问题,没关系,这是你的设计,没有问题。在
init
方法中绑定事件确实更干净。

以您现在的方式绑定事件没有什么错。你失去范围的原因是因为你做了

self = this;
它在构造函数中将self创建为全局变量。因此,每次调用构造函数时,它都会将self设置为该实例

要解决此问题,请在init函数中将self设置为局部变量:

MyObject.prototype = {
  init: function() {
    var self = this;  // <-- this is the fix      
    $(this.element).click(function() {
       self.myfunct();
    });
} 
MyObject.prototype={
init:function(){

var self=this;//好的,首先是关于
self的事情

这一行:

self = this;
您正在创建一个名为
self
的全局变量,该变量在每次调用构造函数时都会被覆盖。如果您使用的是严格模式,则很容易检测到这一点。此外,如果您正确使用局部变量,您的原型将不知道什么是
self
,因此您尝试在原型坏了

我认为你的两种方法都存在问题:

  • 第一种方法需要在MyObject类型之外进行太多的手动工作
  • 第二种方法(如果工作正常)将事件附加到按钮,作为调用构造函数的副作用。这会让使用API的人感到困惑,因为他们希望构造函数创建对象,而不是修改其他现有对象
作为补救办法,我建议采取以下办法:

var MyObject = function(ele) {
    this.element = ele; 
}

MyObject.prototype = {
    attachEvents: function() {        
        var self = this;
        $(this.element).click(function() {
           self.myfunct();
        });
    },
    myfunct: function() {
        console.log('myfunct called');
    }
};

$(document).ready(function() {
    var button = $('#button'),
        myobj = new MyObject(button);

    myobj.attachEvents();
});
这需要实例化
MyObject
的人员执行一个额外的步骤,但它清楚地传达了将事件附加到
MyObject
的封装元素的意图。它也不需要使用
MyObject
的人员执行第一种方法的复杂操作