简体   繁体   English

`this.some_property` 在匿名回调函数中变为未定义

[英]`this.some_property` becomes undefined inside anonymous callback function

So I can't quite figure out why the variable this.tasks becomes undefined inside of the add event listener I have inside of my goal object.所以我不太明白为什么变量this.tasks在我的目标对象中的 add 事件侦听器中变为 undefined 。 I have a feeling it might have something to do with asynchronous programming(which I still don't fully understand).我有一种感觉它可能与异步编程有关(我仍然不完全理解)。 Sorry I'm a bit of a JS noob, but if you guys could explain to me what I'm doing wrong and what might be a better solution that would be awesome!抱歉,我是个 JS 菜鸟,但如果你们能向我解释我做错了什么,以及什么可能是更好的解决方案,那就太棒了! Thanks.谢谢。

function Goal(name) {
        this.gDiv =  document.createElement('div');
        this.name = name || "goal";
        this.tasks = document.createElement('ul');
        //Sets the styling and content and adds it to the parent element
        this.initialize = function() {
            this.gDiv.className = "default";
            this.gDiv.setAttribute("id", this.name);
            this.gDiv.innerHTML = this.name;
            elem.appendChild(this.gDiv);

            this.gDiv.parentNode.insertBefore(this.tasks, this.gDiv.nextSibling);
            this.tasks.style.display = "none";


        };  
        //Creates a list underneath the a dive associated with the Goal object
        this.addTask = function(task) {
            var newLi = document.createElement('li');
                newLi.innerHTML = task;
                this.tasks.appendChild(newLi);
        };

        this.gDiv.addEventListener('click', function(){
            alert(this.tasks);              
        });

    }

Thank you guys!谢谢你们! You all answered my question!你们都回答了我的问题! I'd been scratching my head at this for a while.我一直在挠头一段时间。 Kudos to you all!向大家致敬!

The scope changes when you enter that anonymous closure and 'this' changes.当您输入匿名闭包并且“this”发生变化时,范围会发生变化。 You can hack around it by doing你可以通过做来破解它

var self = this;

And then using self in place of this (eg):然后使用 self 代替这个(例如):

function Goal(name) {
    var self = this;

    /* ... */

    this.gDiv.addEventListener('click', function(){
        alert(self.tasks);              
    });

If you're using jQuery you could do something nicer:如果您使用 jQuery,您可以做一些更好的事情:

this.gDiv.addEventListener('click', $.proxy(function() {
    alert(this.tasks);
 }, this));

Either way works just fine.无论哪种方式都可以正常工作。

EDIT: In ES6, arrow functions can be used instead as they don't bind their own "this", so it becomes even simpler:编辑:在 ES6 中,可以使用箭头函数代替,因为它们不绑定自己的“this”,所以它变得更加简单:

this.gDiv.addEventListener('click', () => {
    alert(this.tasks);
 });

Here is a comparison of some methods (including your problem), to give you a taster, and to try and explain things a little.这是一些方法的比较(包括您的问题),给您一个品尝者,并尝试解释一些事情。

 // This is the problem that you have, // where `this` inside the anonymous function // is a different scope to it's parent function Test1(something) { // `this` here refers to Test1's scope this.something = something; setTimeout(function() { // `this` here refers to the anonymous function's scope // `this.something` is `undefined` here console.log(this.something); }, 1000); }; new Test1('Hello');

 // This solution captures the parent `this` as `test2This`, // which can then be used inside the anonymous function function Test2(something) { var test2This = this; this.something = something; setTimeout(function() { console.log(test2This.something); }, 1000); } new Test2('World');

 // This solution captures `this` as `test3This` in an `IIFE closure` // which can then be used in the anonymous function // but is not available outside of the `IIFE closure` scope function Test3(something) { this.something = something; (function(test3This) { setTimeout(function() { console.log(test3This.something); }, 1000); }(this)); } new Test3('Goodbye');

 // This method requires that you load an external library: jQuery // and then use it's `$.proxy` method to achieve the basics of // Test3 but instead of being referred to as `test3This` the // outer scope `this` becomes the inner scope `this` // Ahh, that's much clearer? function Test4(something) { this.something = something; setTimeout($.proxy(function() { console.log(this.something); }, this), 1000); } new Test4('Mum');
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

 // This is approximately what jQuery's `$.proxy` does // but without having to load the whole library function Test5(something) { this.something = something; setTimeout((function(func, context) { return function() { func.call(context); }; }(function() { console.log(this.something); }, this)), 1000); } new Test5('Dad');

 // Lets create the proxy method as a reuseable function proxy(func, context) { var args = Array.prototype.slice.call(arguments, 2); return function() { return func.apply( context, args.concat(Array.prototype.slice.call(arguments)) ); }; } // and now using it function Test6(something) { this.something = something; setTimeout(proxy(function() { console.log(this.something); }, this), 1000); } new Test6('Me want cookies');

Then we have Function#bind然后我们有Function#bind

 function Test7(something) { this.something = something; setTimeout(function() { // `this` was bound to the parent's `this` using bind console.log(this.something); }.bind(this), 1000); }; new Test7('Num num');
 <script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.min.js"></script>

And most recently ES2015 Arrow functions以及最近的ES2015 箭头函数

 function Test8(something) { this.something = something; setTimeout(() => console.log(this.something), 1000); }; new Test8('Whoop');

In ES6, arrow functions were introduced, which do not bind their own this.在 ES6 中,引入了箭头函数,它们不绑定自己的 this。

MDN for reference . MDN 供参考

So creating an anonymous function using the arrow syntax is probably the easiest way to overcome this issue nowadays.因此,使用箭头语法创建匿名函数可能是当今解决此问题的最简单方法。 It is supported by all major browsers currently, except IE.目前除 IE 外,所有主流浏览器都支持它。

the keyword 'this' changes in it's meaning for an event handler against a constructor关键字“this”改变了它对于构造函数的事件处理程序的含义

please refer to the MDN请参考 MDN

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_a_DOM_event_handler https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_a_DOM_event_handler

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM