从单击回调javascript + jquery调用此对象的方法

时间:2017-07-23 20:44:16

标签: javascript jquery

我有一个类动态创建一个按钮,在单击它时调用输入的函数:

var TestObj = {
    name: "foobar",
    submit: function() {
        alert("my name is: " + this.name);
    },
    init: function() {
        $('<button>').click(function() { this.submit() }).text("hello").appendTo("#entryFormBox");
    }
};

TestObj.init();

(#entryFormBox只是它进入的容器的ID。)

问题是,我收到错误:

未捕获的TypeError:this.submit不是函数

我可以猜到为什么这不起作用(当函数被赋予按钮时,“this”不再意味着“TestObj”,对吧?)。但我仍然迷失了如何以我试图让它工作的方式获得这种功能。我希望在按下按钮时正确调用提交功能。

3 个答案:

答案 0 :(得分:0)

问题是这个是指点击回调函数。试试这个:

&#13;
&#13;
var TestObj = {
    name: "foobar",
    submit: function() {
        alert("my name is: " + this.name);
    },
    init: function() {
         var self=this;
        $('<button>').click(function() { self.submit() }).text("hello").appendTo("#entryFormBox");
    }
};

TestObj.init();
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<dv id="entryFormBox"></div>
&#13;
&#13;
&#13;

关于this关键字:

  

与其他语言相比,此关键字在JavaScript中的行为略有不同。它在严格模式和非严格模式之间也有一些区别。   在大多数情况下,其值取决于函数的调用方式。它不能在执行期间通过赋值来设置,并且每次调用函数时它可能不同。 ES5引入了bind方法来设置函数的值,无论它是如何被调用的,并且ES2015引入了箭头函数,这些函数的词法范围是(它被设置为封闭执行上下文的this值) )。

<强> 1。在全球范围内使用时

在全局上下文中使用this时,它绑定到全局对象(浏览器中为window

document.write(this);  //[object Window]

当在全局上下文中定义的函数中使用this时,this仍然绑定到全局对象,因为该函数实际上是一个全局上下文的方法。

function f1()
{
   return this;
}
document.write(f1());  //[object Window]

以上f1是一个全局对象的方法。因此,我们也可以在window对象上调用它,如下所示:

function f()
{
    return this;
}

document.write(window.f()); //[object Window]

<强> 2。在对象方法中使用时

在对象方法中使用this关键字时,this绑定到&#34;立即&#34;封闭对象。

var obj = {
    name: "obj",
    f: function () {
        return this + ":" + this.name;
    }
};
document.write(obj.f());  //[object Object]:obj

上面我已将单词立即用双引号括起来。重点是,如果将对象嵌套在另一个对象中,则this绑定到直接父对象。

var obj = {
    name: "obj1",
    nestedobj: {
        name:"nestedobj",
        f: function () {
            return this + ":" + this.name;
        }
    }            
}

document.write(obj.nestedobj.f()); //[object Object]:nestedobj

即使您将函数显式添加到对象作为方法,它仍然遵循上述规则,即this仍然指向直接父对象。

var obj1 = {
    name: "obj1",
}

function returnName() {
    return this + ":" + this.name;
}

obj1.f = returnName; //add method to object
document.write(obj1.f()); //[object Object]:obj1

第3。调用无上下文函数时

当你在没有任何上下文的情况下使用this内部函数(即不在任何对象上)时,它被绑定到全局对象(浏览器中的window)(即使定义了函数)在对象内部。)

var context = "global";

var obj = {  
    context: "object",
    method: function () {                  
        function f() {
            var context = "function";
            return this + ":" +this.context; 
        };
        return f(); //invoked without context
    }
};

document.write(obj.method()); //[object Window]:global 

使用功能尝试所有功能

我们也可以尝试以上功能。然而,存在一些差异。

  • 上面我们使用对象文字表示法向对象添加了成员​​。我们可以使用this向函数添加成员。指定它们。
  • 对象文字表示法创建一个我们可以立即使用的对象实例。使用函数,我们可能需要首先使用new运算符创建其实例。
  • 同样在对象文字方法中,我们可以使用点运算符显式地将成员添加到已定义的对象。这仅添加到特定实例。但是我已经在函数原型中添加了变量,以便它反映在函数的所有实例中。

下面我尝试了上面用Object和this做的所有事情,但首先是创建函数而不是直接编写对象。

/********************************************************************* 
  1. When you add variable to the function using this keyword, it 
     gets added to the function prototype, thus allowing all function 
     instances to have their own copy of the variables added.
*********************************************************************/
function functionDef()
{
    this.name = "ObjDefinition";
    this.getName = function(){                
        return this+":"+this.name;
    }
}        

obj1 = new functionDef();
document.write(obj1.getName() + "<br />"); //[object Object]:ObjDefinition   

/********************************************************************* 
   2. Members explicitly added to the function protorype also behave 
      as above: all function instances have their own copy of the 
      variable added.
*********************************************************************/
functionDef.prototype.version = 1;
functionDef.prototype.getVersion = function(){
    return "v"+this.version; //see how this.version refers to the
                             //version variable added through 
                             //prototype
}
document.write(obj1.getVersion() + "<br />"); //v1

/********************************************************************* 
   3. Illustrating that the function variables added by both above 
      ways have their own copies across function instances
*********************************************************************/
functionDef.prototype.incrementVersion = function(){
    this.version = this.version + 1;
}
var obj2 = new functionDef();
document.write(obj2.getVersion() + "<br />"); //v1

obj2.incrementVersion();      //incrementing version in obj2
                              //does not affect obj1 version

document.write(obj2.getVersion() + "<br />"); //v2
document.write(obj1.getVersion() + "<br />"); //v1

/********************************************************************* 
   4. `this` keyword refers to the immediate parent object. If you 
       nest the object through function prototype, then `this` inside 
       object refers to the nested object not the function instance
*********************************************************************/
functionDef.prototype.nestedObj = { name: 'nestedObj', 
                                    getName1 : function(){
                                        return this+":"+this.name;
                                    }                            
                                  };

document.write(obj2.nestedObj.getName1() + "<br />"); //[object Object]:nestedObj

/********************************************************************* 
   5. If the method is on an object's prototype chain, `this` refers 
      to the object the method was called on, as if the method was on 
      the object.
*********************************************************************/
var ProtoObj = { fun: function () { return this.a } };
var obj3 = Object.create(ProtoObj); //creating an object setting ProtoObj
                                    //as its prototype
obj3.a = 999;                       //adding instance member to obj3
document.write(obj3.fun()+"<br />");//999
                                    //calling obj3.fun() makes 
                                    //ProtoObj.fun() to access obj3.a as 
                                    //if fun() is defined on obj3

<强> 4。在构造函数内部使用时。

当函数用作构造函数时(即使用new关键字调用它时),函数体内的this指向正在构造的新对象。

var myname = "global context";
function SimpleFun()
{
    this.myname = "simple function";
}

var obj1 = new SimpleFun(); //adds myname to obj1
//1. `new` causes `this` inside the SimpleFun() to point to the
//   object being constructed thus adding any member
//   created inside SimipleFun() using this.membername to the
//   object being constructed
//2. And by default `new` makes function to return newly 
//   constructed object if no explicit return value is specified

document.write(obj1.myname); //simple function

<强> 5。在原型链中定义的函数内部使用时

如果方法在对象的原型链上,则此方法中的this引用调用该方法的对象,就像在对象上定义了该方法一样。

var ProtoObj = {
    fun: function () {
        return this.a;
    }
};
//Object.create() creates object with ProtoObj as its
//prototype and assigns it to obj3, thus making fun() 
//to be the method on its prototype chain

var obj3 = Object.create(ProtoObj);
obj3.a = 999;
document.write(obj3.fun()); //999

//Notice that fun() is defined on obj3's prototype but 
//`this.a` inside fun() retrieves obj3.a   

<强> 6。内部call(),apply()和bind()函数

  • 所有这些方法都在Function.prototype上定义。
  • 这些方法允许编写一次函数并在不同的上下文中调用它。换句话说,它们允许指定在执行函数时将使用的this的值。它们还会在调用时将任何参数传递给原始函数。

答案 1 :(得分:0)

您可以使用Function.prototype.bind()$.proxy()设置函数调用的this,因为jQuery事件处理程序中的this设置为DOM元素默认情况下

&#13;
&#13;
var TestObj = {
  name: "foobar",
  submit: function() {
    alert("my name is: " + this.name);
  },
  clickHandler: function() {
    this.submit()
  },
  init: function() {
    $('<button>').click(this.clickHandler.bind(this))
    .text("hello")
    .appendTo("#entryFormBox");
  }
};

TestObj.init();
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="entryFormBox"></div>
&#13;
&#13;
&#13;

&#13;
&#13;
var TestObj = {
  name: "foobar",
  submit: function() {
    alert("my name is: " + this.name);
  },
  init: function() {
    $('<button>').click(
      $.proxy(function() {
        this.submit()
      }, this)
    )
    .text("hello")      
    .appendTo("#entryFormBox");
  }
};

TestObj.init();
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="entryFormBox"></div>
&#13;
&#13;
&#13;

答案 2 :(得分:-1)

试试这个:

var TestObj = {
    name: "foobar",
    submit: function() {
        alert("my name is: " + this.name);
    },
    init: function() {
        $('<button>').click(function() { TestObj.submit() }).text("hello").appendTo("#entryFormBox");
    }
};

TestObj.init();