gpt4 book ai didi

javascript - 验证我对作用域链的理解

转载 作者:行者123 更新时间:2023-11-29 18:19:12 24 4
gpt4 key购买 nike

(问题 1)在 Flanagan 的 JS 权威指南中,他定义了 Function 方法 bind() 以防它不可用(在 ECMAScript 3 中不可用)。

看起来像这样:

function bind(f, o) {
if (f.bind) return f.bind(o); // Use the bind method, if there is one
else return function() { // Otherwise, bind it like this
return f.apply(o, arguments);
};
}

他用一个例子说明了它的用法(我修改了它以更改 f.bind(o) 的第 3 行):

function f(y) { return this.x + y; } // This function needs to be bound
var o = { x : 1 }; // An object we'll bind to
var g = bind(f, o); // Calling g(x) invokes o.f(x)
g(2) // => 3

当我第一次看到这个时,我想“arguments 不会引用我们正在定义的绑定(bind)函数中的参数变量吗?但是我们想要最终应用它的函数的参数属性就像上面例子中的 g...”

我验证了他的示例确实有效,并推测 return f.apply(o, arguments) 行直到 var g = bind(f, o)< 才被评估 上面。也就是说,我想,当你返回一个函数时,你只是返回那个函数的源代码,不是吗?直到它被评估?所以我通过尝试一个稍微不同的绑定(bind)版本来测试这个理论:

function mybind2(f, o) {
var arguments = 6;
return function() { // Otherwise, bind it like this
return f.apply(o, arguments);
};
}

如果它只是简单地返回未计算的函数源,那么在以后计算时它不可能存储 arguments = 6,对吗?在检查之后,我仍然得到 g(2) => 3。但后来我意识到——如果它只是返回未评估的代码, 中的 o 怎么样? return f.apply(o, arguments) 通过了吗?

所以我决定一定要发生的事情是这样的:

oarguments 变量(即使 arguments 等于 6) 正在传递给功能。只是当函数 g 最终被调用时,arguments 变量被解释器重新定义为 g 的参数(在 g(2)),因此我尝试传递的参数的原始值被替换了。但这意味着直到那时它都是将函数存储为文本,因为否则 oarguments 将只是程序中的数据,而不是可能的变量被覆盖。这个解释对吗?

(问题 2) 在同一页的前面,他定义了以下函数,该函数使用 apply 方法来跟踪函数以进行调试:

function trace(o, m) {
var original = o[m]; // Remember original method in the closure.
o[m] = function() { // Now define the new method.
console.log(new Date(), "Entering:", m); // Log message.
var result = original.apply(this, arguments); // Invoke original.
console.log(new Date(), "Exiting:", m); // Log message.
return result; // Return result.
};
}

这里的 this 不是指我们定义的函数,而不是对象 o 吗?或者这两者是一回事?

最佳答案

问题一

对于您的第一个问题,让我们简化示例,以便清楚要做什么:

function bind(func, thisArg) {
return function () {
return func.apply(thisArg, arguments);
};
}

这里发生的是创建一个闭包,允许访问原始函数和传递的 this 的值。返回的匿名函数会将原始函数保留在其范围内,最终如下所示:

var func = function () {};
var thisArg = {};
func.apply(thisArg, [/*arguments*/]);

关于您的arguments 问题,该变量隐式定义在创建的所有函数的范围内,因此内部arguments 将隐藏外部参数,使其按预期工作。

问题2

你的问题是你对 this 的后期绑定(bind)的误解——对于习惯于更多面向对象语言的人来说,这是 JavaScript 中最令人困惑的事情之一,这些语言也有自己的 this 关键字。 this的值只在调用时设置,调用的地方定义了调用时this的值。它只是调用函数时父对象的值this 值被覆盖的情况除外。

例如,看这个:

function a() {return this;};
a(); // global object;
var b = {};
b.a = a;
b.a(); // object b

如果在定义函数时设置了 this,则调用 b.a 将生成全局对象,而不是 b 对象。让我们也简化给出的第二个函数所发生的事情:

function trace(obj, property) {
var method = obj[property]; // Remember original method in the closure.
obj[property] = function () { // Now define the new method.
console.log(1); // Log message.
// Invoke original method and return its result
return original.apply(this, arguments);
};
}

在这种情况下发生的是原始方法存储在闭包中。分配给方法最初所在的对象不会覆盖 method 对象。就像普通的方法赋值一样,this 值的原理仍然相同——它将返回父对象,而不是您定义的函数。如果你做一个简单的任务:

var obj = {};
obj.foo = function () { return this; };
obj.foo(); // obj

它做了预期的事情,返回调用时的父对象。在这方面,将您的代码放在嵌套函数中没有任何区别。

一些不错的资源

如果您想了解更多有关使用 JavaScript 编写代码的信息,我强烈建议您查看 Fully Understanding the this Keyword作者:Cody Lindley —— 它更详细地介绍了 this 关键字在不同上下文中的行为方式以及您可以使用它做的事情。

关于javascript - 验证我对作用域链的理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20461963/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com