1

我经历了很多帖子,我终于得到了我需要的东西,这要归功于:

$("a.foo").click(function(){
    var that = this;
    jPrompt("Type something:","","", function(r) {
        $(that).text(r);
    }
}

来自以下内容: 在回调函数中访问 $(this)

我想知道是否有人可以扩展这里到底发生了什么(为什么this不重新分配就不能使用?)以及我应该阅读哪些核心信息?据我所知,这可能与闭包有关……这是我在四处搜索时遇到的大部分内容。那准确吗?

就我而言,我希望执行一些代码,然后在 ajax 请求完成后重定向。在我正在运行的回调函数$(this).attr("href")中返回未定义。

4

4 回答 4

3

this由javascript根据函数的调用方式分配。因此,当调用 回调时,该jPrompt()函数决定了回调中的值。thisjPrompt()

因此,除非 jPrompt 不遗余力地this通过您传入的某些参数保持相同的值,否则它可能具有不同的值。因此,您可以将其保存起来以便在回调中访问,就像您所做的那样。这是 javascript 回调中非常常见的设计模式。

仅供参考,this分配的一些方式:

  • obj.method()- thisinmethod()将设置为obj
  • func.call(obj)- thisinfunc()将设置为obj
  • func()-this将设置为window严格模式func()undefined严格模式
于 2012-12-02T03:11:40.583 回答
1

问题中的代码带有一些添加的注释:

$("a.foo").click(function(){
    var that = this; //`this` holds the a object clicked.  now so does `that`! 
    jPrompt("Type something:","","", function(r) { 
        //even if `this` has a different value here, `that` still holds the a object clicked
        $(that).text(r);
    }
}

这是您经常会发现自己在类似情况下所做的事情。 this是上下文相关的,您经常需要将值保留this在一个上下文中并在另一个上下文中使用它。

来自 ECMAScript 规范的引用:

10.1.7 这个

每个活动的执行上下文都有一个this值。this值取决于调用者和正在执行的代码类型,并在控制进入执行上下文时确定。

希望这能回答你的问题。您还要求提供进一步阅读的资源。请拜访:

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

这些人提供了详细且通常非常准确的优秀文档(不像其他流行的参考来源,通常首先出现在 Google 搜索中——w3cshools.com 我在想你!)。

于 2012-12-02T03:14:38.123 回答
1

含义的this变化取决于你在哪里。this单击事件的内部处理程序意味着this传递给您的jPrompt函数的回调内部以外的其他内容。

对于它的价值,您不需要重新分配this,因为event传递给您的处理程序的对象将引用currentTarget

$("a.foo").on("click", function (event) {
    // 'this' here refers to the anchor we clicked
    jPrompt("Type something:", "", "", function (r) {
        // 'this' here refers to whatever jPrompt instructs
        $(event.currentTarget).text(r);
    }
}
于 2012-12-02T03:17:18.223 回答
1

简要概述this

this在 JavaScript 中是动态作用域的。它的行为不同于所有其他词法范围的变量。其他变量没有不同的绑定,具体取决于函数的调用方式;它们的范围来自它们在脚本中出现的位置。this但是行为不同,并且可以具有不同的绑定,这取决于它在脚本中出现的位置,而取决于它的调用方式。因此,对于学习这门语言的人来说,它可能是一个困惑的根源,但要成为一名熟练的 JavaScript 开发人员,掌握它是必要的。

由于this是动态绑定的,因此有多种方法可以根据您调用函数的方式更改其值。


例子

在 JavaScript 中执行函数时,默认this值为window.

function foo() {
    console.log(this);
}

foo(); // => window

this可以通过多种方式更改该值。一种方法是将函数作为对象的方法调用:

var x = {
    foo: function() {
        console.log(this);
    }
};
x.foo(); // => This time it's the x object.

另一种方法是使用callapply告诉函数在某个对象的上下文中执行。

function foo() {
    console.log(this);
}
foo.call(x); // => x object again
foo.apply(x); // => x object as well

如果你callapplynullundefined,默认行为将再次发生:该函数将在上下文中执行window

function foo() {
    console.log(this);
}
foo.call(null); // => window
foo.apply(undefined); // => window

但是,请注意,在 ECMAScript 5严格模式下this不默认为窗口:

(function() {

    'use strict';

    function foo() {
        console.log(this);
    }

    foo(); // => undefined
    foo.call(null); // => null
    foo.apply(undefined); // => undefined

})();

您还可以在调用函数之前将其设置为thisbind函数绑定到对象:

function foo() {
    console.log(this);
}

var bar = {
    baz: 'some property'
};

var foobar = foo.bind(bar);

foobar(); // => calls foo with bar as this

成为父亲:懒惰的绑定/ Uncurryingthis

更进一步,您有时可能希望采用作用于 athis并允许将this值作为函数的第一个参数传入的函数。这对于 Array 方法非常有用,例如forEach. 例如,假设您正在处理一个类似数组但实际上不是数组的对象。

var arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    'length': 3
};

如果你想用 迭代这个对象forEach,你可以使用call

Array.prototype.forEach.call(arrayLike, function(item) {
    console.log(item);
});
// Logs: a, b, c

但是,另一种选择是创建一个forEach可以直接在您的对象上调用的函数:

var forEach = Function.prototype.call.bind(Array.prototype.forEach);

现在,您可以在任何时候想要迭代类似数组的对象时使用此函数:

forEach(arrayLike, function(item) {
    console.log(item);
});
// Logs: a, b, c

有时这种方法被称为“uncurrying this”。但是,我更喜欢创建一个可以生成这些“非curried”函数并将其称为“惰性绑定”的函数。

var lazyBind = Function.prototype.bind.bind(Function.prototype.call);

var forEach = lazyBind(Array.prototype.forEach);
var slice = lazyBind(Array.prototype.slice);
var map = lazyBind(Array.prototype.map);

forEach(arrayLike, function(u) {
    console.log(u);
});
// Logs: a, b, c

var realArray = slice(arrayLike);
// Converts arrayLike into a real array

forEach(
    map(arrayLike, function(u) {
        return u + 'Q';
    }),
    function(u) {
        console.log(u);
    }
);
// Logs: aQ, bQ, cQ

关于这种技术的一个非常棒的事情是它可以用于创建安全的 JavaScript,如果您不希望页面上的其他脚本窥探您的内部变量,这将很有帮助。不过,这是一种非常先进的元编程技术,您在日常 JavaScript 中看不到它。

于 2012-12-02T06:00:56.140 回答