关于函数的参数范围和document.writeln

时间:2014-02-07 12:20:27

标签: javascript arguments

我正在阅读“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显示'undefined'(在评论[E]中)
  6. 的原因

    显示该代码后,我会解释更多。

    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]参数[1],[D]参数[0],[D]参数[1]没有值。所以它们是“未定义的”,对吧。

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

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

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

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

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

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


    我明白了..

    中的参数是绑定函数的参数

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

    右?

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

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

1 个答案:

答案 0 :(得分:0)

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)会更容易 - 它们是一样的。

  

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

不是undefined,而是空数组[]

  

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

bind需要进一步的可选参数。你没有通过。

  

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

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

  

参数未定义。嗯...那么这会返回参数[0]?这是{值: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, …