关于JavaScript构造函数和匿名函数的一些问题
我有以下 JavaScript 函数:
function Console() {
this.Log = function(msg) {
if (document.getElementById("console")) {
var console = document.getElementById("console");
console.innerHTML += msg + "<br/>";
}
}
}
问题 1: 为什么我需要使用新的关键字?
new Console().Log("hello world");
为什么我不能这样做?
Console().Log("hello world without using new");
问题2:
var logger = function() {
this.log = function(msg) {
new Console().Log(msg);
new Console().Log("log initialized");
}
this.log2 = function(msg) {
new Console().Log(msg);
new Console().Log("log2 initialized");
}
}(); //notice the brackets
由于记录器末尾有(),因此无法运行。
new logger().log("hello world");
我知道尾随 () 意味着该函数被立即调用,但为什么它不起作用?是因为 function() {} ();不能分配给其他变量吗?
I have the following JavaScript function:
function Console() {
this.Log = function(msg) {
if (document.getElementById("console")) {
var console = document.getElementById("console");
console.innerHTML += msg + "<br/>";
}
}
}
Question 1:
Why do I need to use new key word?
new Console().Log("hello world");
Why couldn't I just do this?
Console().Log("hello world without using new");
Question 2:
var logger = function() {
this.log = function(msg) {
new Console().Log(msg);
new Console().Log("log initialized");
}
this.log2 = function(msg) {
new Console().Log(msg);
new Console().Log("log2 initialized");
}
}(); //notice the brackets
This wouldn't run because of the () at the end of logger.
new logger().log("hello world");
I know with the trailing () it means the function is called immediately but why wouldn’t it work? Is it because function() {} (); can't be assigned to other variables?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
new
关键字创建Console
对象的实例,然后您可以在其上调用Log
方法。如果您直接调用Console()
,您将获得该函数的返回值。在您的情况下,没有,因此未定义
。此外,如果您不使用new
关键字,则在该“类函数”内分配给this
的任何内容都会污染全局范围。因此,您不必将方法分配给this
,而是必须使用要返回的代理对象。在您的示例中,您将
logger
变量分配给调用匿名函数的返回值。同样,它不会返回任何内容,因此调用new logger()
将不起作用,因为您无法实例化undefined
。因此,从匿名函数中删除尾部()
会将 function 分配给logger
而不是其返回值,然后您可以使用它进行实例化新
。 (您也可以再次使用代理对象)。在上面的两个示例中,我强烈建议使用
new
关键字,而不是创建并返回代理对象。这利用了 Javascript 内置的实例化机制和函数原型链,并且比对象创建快得多。John Resig 的这篇博文值得一读,了解有关 Javascript 中“类”实例化如何工作的更多信息:http://ejohn.org/blog/simple-class-instantiation/
The
new
keyword creates an instance of yourConsole
object which you can then call theLog
method on. If you just callConsole()
directly, you'll get whatever the return value is for that function. In your case there is none, soundefined
. Additionally, if you don't use thenew
keyword, anything you assign tothis
within that "class function" will pollute the global scope. So instead of assigning your methods tothis
, you'd have to use a proxy object which you would return instead.In your example you're assigning the
logger
variable to the return value of calling your anonymous function. Again, it doesn't return anything so callingnew logger()
won't work because you can't instantiateundefined
. So, removing the trailing()
from the anonymous function will assign the function tologger
rather than its return value, which you can then instantiate withnew
. (You could also use a proxy object again).In both the above examples, I'd strongly advise using the
new
keyword rather than creating and returning a proxy object. This takes advantage of Javascript's built in instantiation mechanism and the function prototype chain, and is much faster than object creation.This blog post by John Resig is worth a read for more information on how "class" instantiation works in Javascript: http://ejohn.org/blog/simple-class-instantiation/
答案1:
您将“日志”功能添加到“this”中。这就是您必须先从控制台函数创建对象才能访问它的原因。
当您执行 Console().Log() 时,您正在尝试运行 Console 函数并在返回的对象上调用“Log”方法。因为 Console 函数不返回任何内容,所以它是“未定义”的,因此您无法访问 Log 方法。
答案2:
“logger”不是一个函数,而是匿名函数输出的结果。
您的匿名函数不会返回任何内容,因此记录器将是“未定义”。对于未定义的对象,没有“log”方法。
要解决这个问题,请执行以下操作:
了解 JS 中的函数和对象创建
您必须了解的主要内容是,在 JavaScript 中,当使用“new”关键字调用时,常规函数充当“构造函数”。
考虑以下功能。
当您像这样调用上面的函数时,
“this”将是“window”对象,并且它将添加值为“Console”的“name”属性。
如果您像这样调用上面的函数,
JavaScript 将创建一个新对象,可以使用“Console”内的“this”访问该对象。现在输出将具有“名称”属性。
如果以上内容还不能帮助您解决问题,请告诉我。您必须了解它才能利用 JS 提供的功能。
Answer 1:
You added the 'Log' function to the 'this'. That's the reason you have to create object from Console function before you can access it.
When you do Console().Log(), you are trying to run Console function and call 'Log' method on the returned object. Because Console function doesn't return anything, it is 'undefined' and hence you can't access the Log method.
Answer 2:
The 'logger' is not a function but result of the anonymous function output.
Your anonymous function doesn't return anything so logger will be 'undefined'. And for an undefined object, there is no 'log' method.
To solve this problem, do this:
Understanding function and Object creation in JS
The main thing you have to understand is that in JavaScript, a regular function acts as a 'constructor' when called with 'new' keyword.
Consider following function.
When you call above function like this,
'this' will be the 'window' object and it will add 'name' property with the value of 'Console'.
If you call the above function like,
JavaScript will create a new object which is accessible using 'this' inside 'Console'. Now output will have 'name' property.
Let me know if above doesn't clear up things for you. It's essential that you understand it to be able to take advantage of what JS has to offer.
正如您所指出的,当您执行
function(){}()
时,您将立即定义并调用函数。因此,当您遇到以下情况时:您将指定
logger
作为该函数的返回值,而不是函数本身。在您的示例中,该函数不返回任何内容,因此logger
将是未定义的。正如风格问题,在编写立即调用的匿名函数时,将函数括在括号中是相当标准的:这只是向读者提供一个视觉提示,表明您将要调用该函数,可以避免很多混乱。实际上,在某些情况下这样做相当重要:请参阅下面的评论!When you do
function(){}()
you are defining and calling a function immediately, as you pointed out. Therefore when you have this:You are assigning
logger
to be the return value of that function, not the function itself. In your example, the function returns nothing, thereforelogger
will be undefined.Just as a matter of style,when writing anonymous functions which are called immediately, it's pretty standard to wrap the function in parentheses:It's just a visual hint to the reader that you are going to be calling that function, and it can save a lot of confusion.Actually, it's rather important to do that in some situations: see the comments below!