javascript中的回调函数错误
我正在学习回调函数。我不明白为什么这两个代码块之间有区别。有人能解释一下吗javascript中的回调函数错误,javascript,function,Javascript,Function,我正在学习回调函数。我不明白为什么这两个代码块之间有区别。有人能解释一下吗 function a(callback) { var something = 10; callback(); } a(function() { console.log(something); }); 这是: function a() { var something = 10; (function() { console.log(something); }())
function a(callback) {
var something = 10;
callback();
}
a(function() {
console.log(something);
});
这是:
function a() {
var something = 10;
(function() {
console.log(something);
}());
}
a();
function getUserInput() {
clientData.setUserName('viet','nguyen')
}
getUserInput();
console.log(clientData.fullName);
// it will return the object clientData and the fullname set to viet nguyen
我还对这两个代码块感到困惑:
var clientData = {
id: 094545,
fullName: "Not Set",
setUserName: function (firstName, lastName) {
var self = this;
self.fullName = firstName + " " + lastName;
console.log(self);
} }
function getUserInput(firstName, lastName, callback) {
callback (firstName, lastName);
}
getUserInput('viet','nguyen',clientData.setUserName );
console.log(clientData.fullName);
// It will return the window object and not set
这是:
function a() {
var something = 10;
(function() {
console.log(something);
}());
}
a();
function getUserInput() {
clientData.setUserName('viet','nguyen')
}
getUserInput();
console.log(clientData.fullName);
// it will return the object clientData and the fullname set to viet nguyen
下面是对第一个代码块对的解释:
通常,一个应用程序需要按顺序执行许多函数,大多数情况下都是这样,比如说你有一个寄存器函数,但当它成功时,你希望引导用户进入下一步。因此,这里我们可以调用一个名为register()的函数,当该函数完成时,它将自动调用我们希望它在成功时执行的函数,或者现在使用多个回调也变得很常见 现在,在这些情况下,许多人用它来表示成功或失败。使用这些函数时,可以传递两个函数,一个显示成功消息,另一个显示错误。下面的例子
function register(onsuccess, onfailure) {
try {
... Some logic here ...
onsuccess();
}
catch(err) {
onfailure();
}
}
使用另一种不使用回调的方法,我们必须这样做
function register() {
try {
... Some logic here ...
return true;
}
catch(err) {
return false;
}
}
if (register()) {
... onsuccess logic goes here ...
} else {
... onfailure logic goes here ...
}
正如您所见,回调方法更易于阅读,也更易于调试和维护
希望这已经回答了您的问题并澄清了您可能存在的顾虑:)
编辑:我还想提到,当使用回调函数时,程序员总是更容易创建条件来执行回调
//它将返回窗口对象,但未设置
这是因为当函数引用作为参数传递时,执行上下文会发生变化
function a() {
var something = 10;
(function() { // This is a closure
console.log(something); // The same `something` defined above
}());
}
a();
这条线
getUserInput('viet','nguyen',clientData.setUserName );
在全局上下文(window
)中执行,而不是在clientData
的上下文中执行,因此传递的任何参数都是在调用方的上下文中传递的
按照
让callerContext作为正在运行的执行上下文
在本例中,callerContext是窗口
这是两个独立的问题
第一对代码段
问题在于变量的范围。在这个函数中,您在函数a
中声明一个something
。传递到a
的回调声明在a
的范围之外,因此对something
一无所知,因为something
是局部作用域而不是全局作用域
function a(callback) {
var something = 10; // This is a local variable
callback();
}
a(function() {
console.log(something); // What is `something`???
});
要修复它,您可以像这样将某物传递到回调中:
function a(callback) {
var something = 10; // This is still a local variable
callback(something);
}
a(function(whatever) {
// `whatever` is a new local variable that references `something`.
console.log(whatever);
});
对于您编写的此函数的另一个版本,函数中定义了某个
,因为它是在a
函数中定义的,使其成为一个。因此,它是一个closure拥有闭包是很方便的,但是如果您正在编写一个依赖于回调的函数,那么它很可能是异步的,回调将在其他地方定义,因此最好将数据作为参数传入
function a() {
var something = 10;
(function() { // This is a closure
console.log(something); // The same `something` defined above
}());
}
a();
有闭包是很方便的,但是如果您正在编写一个依赖于回调的函数,它很可能是异步的,回调将在其他地方定义,因此最好将数据作为参数传入
function a() {
var something = 10;
(function() { // This is a closure
console.log(something); // The same `something` defined above
}());
}
a();
第二对代码段
调用函数时,会传入一个隐式函数。调用clientData.setUserName()
大致相当于说clientData.setUserName.call(clientData)
。传入的第一个参数是将分配给此
的对象。但是,如果您将函数clientData.setUserName
作为回调传递给某个对象,并调用该函数,则更等同于说clientData.setUserName.call(this)
,其中this
不再是clientData
(除非您在clientData
上调用另一个函数)。如果此
未被覆盖,它将引用全局对象。在web浏览器中,这将是窗口
。一种可能的解决方案是,在调用函数时,使用覆盖此
将是什么:
function getUserInput(firstName, lastName, callback) {
callback(firstName, lastName);
}
getUserInput('viet','nguyen',clientData.setUserName.bind(clientData));
另一种可能的解决方案是在回调中传入clientData
,尽管这是一种不太可靠的解决方案,因为这意味着getUserInput
将始终使用clientData
,而不是让调用者决定:
function getUserInput(firstName, lastName, callback) {
callback.call(clientData, firstName, lastName);
}
getUserInput('viet','nguyen',clientData.setUserName);
@MarcosPérezGude他要求的是解释,而不是代码审查。@MarcosPérezGude在帮助中心的主题中特别列出,在非主题问题的描述下:“故障排除、调试或理解代码片段”(我的重点)。这个问题对于代码审查来说是特别离题的。@MarcosPérezGude不!不不关于理解代码片段的询问在代码评审中被列为非主题。没有含糊不清的地方。请停止混淆操作。其中一个最接近的原因是:“问题必须涉及您拥有或维护的真实代码。伪代码、假设代码或存根代码应该被具体实现所取代。寻求对其他人代码的解释的问题也离题。”@MarcosPérezGude这是真的,如果OP需要代码的反馈。就这个问题而言,OP想要对代码进行解释,但这是不一样的。事实是:这个问题将在代码审查时立即结束。@MarcosPérezGude这个问题对于程序员来说并不合适——它将很快被否决并在那里结束,请参见。建议阅读:。请不要推荐你不熟悉的网站谢谢你的帮助,我知道我可以使用bind或call,但我想做一点改变,就是这样,你说你对第二对