【问题标题】:About scope of arguments and document.writeln in function关于函数中的参数范围和 document.writeln
【发布时间】:2014-03-04 20:37:28
【问题描述】:

我正在阅读“JavaScripts The Good Parts”(Douglas Crockford 着)。很好。 我无法理解以下代码。它工作正常。但我无法理解它是如何工作的。 关于这段代码有 5 个问题。

  1. 参数的值(我在评论中将它们检查为 [A]、[B])
  2. document.writeln 在函数中不起作用(即不显示任何内容)的原因(我在评论中检查了测试位置为 [C]、[D])
  3. 此代码中的切片结果(在 [A]、[B] 中)
  4. 变量 args 的值(在 [A]、[B] 中)
  5. document.writeln 显示“未定义”的原因(在注释 [E] 中)

在展示完代码后,我会解释更多。

var myTest = {};

Function.prototype.method = function(name, func) {
  if(!this.prototype[name])
  {
    this.prototype[name]=func;
  }
};

Function.method('bind', function(that) {
  var method = this,
  slice = Array.prototype.slice,
  args = slice.apply(arguments, [1]);    //[A] value of arguments and args 

  //-------------------------------
  //[C] following document.writeln do not work. why?
  document.writeln("<C>arguments[0]:", arguments[0]);
  document.writeln("<C>arguments[1]:", arguments[1]);
  document.writeln("<C>args:",args);
  myTest.str1 = 1;
  myTest.str2 = "ABC";
  document.writeln("<C>str1:", myTest.str1);
  document.writeln("<C>str2:", myTest.str2);
  //-------------------------------

  return function(){

     //-------------------------------
     //[D] following document.writeln do not work. why?
     document.writeln("<D>arguments[0]:", arguments[0]);
     document.writeln("<D>arguments[1]:", arguments[1]);
     document.writeln("<D>args:",args);
     myTest.str3 = 2;
     myTest.str4 = "DEF";
     document.writeln("<D>str3:", myTest.str3);
     document.writeln("<D>str4:", myTest.str4);
     //-------------------------------

      return method.apply(that, args.concat(slice.apply(arguments, [0])));    //[B] value of arguments and args 
    };
  });

var x= function(){
  return this.value;
}.bind({value:666});

//-------------------------------
document.writeln("str1:", myTest.str1, "<br/>");   //[E]show undefined. why?
document.writeln("str2:", myTest.str2, "<br/>");   //[E]show undefined. why?
document.writeln("str3:", myTest.str3, "<br/>");   //[E]show undefined. why?
document.writeln("str4:", myTest.str4, "<br/>");   //[E]show undefined. why?
//-------------------------------

alert(x());    //666 -> no problem

[C]、[D]、[E] 中的document.writeln 用于测试。但它们并没有像我预期的那样工作。 警报“666”运行良好。 (没问题)

请帮帮我……

----------- 在 Function.prototype.method 中删除 if-confition 后,我得到以下结果

[C]arguments[0]:[object Object]
[C]arguments[1]:undefined
[C]args:
[C]str1:1
[C]str2:ABC
str0C:[object Object]
str1C:undefined
str0D:undefined
str1D:undefined
str1:1
str2:ABC
str3:undefined
str4:undefined
[D]arguments[0]:undefined
[D]arguments[1]:undefined
[D]args:
[D]str1:2
[D]str2:DEF
str0C:[object Object]
str1C:undefined
str0D:undefined
str1D:undefined
str1:1
str2:ABC
str3:2
str4:DEF

现在,我想知道 [C]、[D] 中参数的实际值、数组的内容...

使用 JSON.stringify(arguments[0])),我终于得到了参数的真正价值。

[C]arguments[0]:{"value":666}

这是我真正想要的。 [C]arguments[1]、[D]arguments[0]、[D]arguments[1] 没有值。所以它们是“未定义的”,对吧。

现在,我想知道什么是“args = slice.apply(arguments, [1]);”在 [A] 中执行。

args = slice.apply(arguments, [1]);

据我所知, slice 返回数组的副本。因为我们使用 apply,所以 slice 使用参数作为 this,[1] 作为参数数组。此时,参数只有一项 {"value":666"}。 slice(start, end) 返回从 'start' 开始并以 'end' 结束的数组副本。然后,在这种情况下 slice.apply( arguments, [1]) 必须返回从 1 开始的 arguments 的副本。但是我们知道 arguments 只有 1 项,所以 arguments[1] 不存在。(arguments[0], {value:666} 存在。) 然后这是如何工作的?args 是未定义的。这是做什么的?有什么我忽略的吗?

在 [B] 中,它返回“method.apply(that, args.concat(slice.apply(arguments, [0])));”。

return method.apply(that, args.concat(slice.apply(arguments, [0])));

在此,[0] 是参数数组。 0.. 为什么是零?参数是未定义的。嗯...那么这会返回 arguments[0]?那是 {value:666}?并警告'666'?


我明白了..

[A] 中的参数是绑定函数的参数

[B] 中的参数是 x 函数的参数

对吗?

现在有一个(也许是最后一个)问题.. ^^ 当我调用 document.writeln.bind(document,"TEST") 时, Function.method('bind', function(that) 中的 'that' 是什么?

'那个'是文件?或“那”是[文档,“测试”]

【问题讨论】:

  • 我修正了一些拼写错误
  • 我在帖子中添加了其他问题。我想知道[C],[D]中参数的真实内容
  • 我在帖子中添加了其他问题^^;;我想知道为什么 [1], [0] 用于应用功能
  • 也许是最后一个问题...^^ 我在帖子末尾添加了这个。 (当我调用 document.writeln.bind(document,"TEST") 时,那是什么?)

标签: javascript arguments


【解决方案1】:
Function.prototype.method = function(name, func) {
    if(!this.prototype[name])

……是你的问题。您没有覆盖现有函数 - 并且 Function.prototype.bind 确实已经存在(并且与您定义的结果相同,但没有记录)。这样,您就不会用您的自定义实现覆盖它,并且您的任何document.writeln 调用或myTest 分配都不会被执行。

您可以出于测试目的删除 if 条件,它会起作用。一旦您在输出中看到发生了什么,您应该能够自己回答其他问题。


现在,我想知道 [C]、[D] 中参数的实际值、数组的内容...

只有一个对象有问题:{value:666} :-) 您可以使用 JSON.stringify 输出它:

document.writeln("<C>arguments[0]:", JSON.stringify(arguments[0]));
…

[slicing] 然后,在这种情况下 slice.apply(arguments, [1]) 必须返回从 1 开始的参数副本。

是的。顺便说一句,写slice.call(arguments, 1) 会更容易——它们是一样的。

但我们知道参数只有一项,所以 arguments[1] 不存在。(arguments[0], {value:666} 存在。) 那么这是如何工作的呢? args 未定义。

不是undefined,而是空数组[]

这是做什么的?有什么我忽略的吗?

它需要更多的可选参数到bind。你没有通过。

在 [B] 中,它返回“method.apply(that, args.concat(slice.apply(arguments, [0])));”。在此,[0] 是参数数组。 0.. 为什么是零?

因为您想获取绑定函数的所有(可选)参数 - 从头开始​​切片。

而且参数是未定义的。嗯...那么这会返回 arguments[0]?那是 {value:666}?并提醒'666'?

arguments 不是未定义的,但长度为 0,因此整个 args.concat(…) 计算为一个空数组。 that 仍然指向 {value: 666},是的 - 这是将传递给 this 关键字的内容。

那么所有这些可选参数是关于什么的?

在您的x 示例中,您只使用了this,您的函数实际上并没有任何参数。但它可能有——让我们尝试一个有更多参数的,比如console.log

var logger = console.log.bind(console, "Here:");
logger(); // Here:
logger(5); // Here: 5
logger({value:666}); // Here: {value: 666}

如果您(还)对控制台不满意,您同样可以使用document.writeln.bind(document, …

【讨论】:

  • 谢谢^^我还有其他问题。正如你所说,Function.prototype.method 已经存在。然后,在我看来,Function.method('bind', function(that)) 必须使用“已经存在的”Function.method 工作。但它没有用。当然,当我删除 if-condition document.writeln 时效果很好。
  • 是的,Function.method('bind', …) 让原始方法保持不变。已经存在的功能 确实 工作 - 您最终会按预期警告 666。
  • 你是对的^^;;我在帖子中添加了其他问题。我想知道为什么 [1], [0] 用于应用功能
  • 我的天啊..^^ [A] 中的参数是绑定的参数。 [B] 中的参数是 x 的参数。正确的?我还有其他(也许是最后一个)问题...^^我在帖子末尾添加了这个问题。 (当我调用 document.writeln.bind(document,"TEST") 时,那是什么?)
  • that 参数是您传递 document 的位置,因此它成为“writeln 函数中的this keyword” - 因此它的行为与 方法调用document.writeln(…):-)
猜你喜欢
  • 2017-08-16
  • 1970-01-01
  • 2011-08-21
  • 1970-01-01
  • 2011-09-19
  • 1970-01-01
  • 2012-11-20
  • 2013-12-25
  • 2017-12-28
相关资源
最近更新 更多