这个守则做了什么?

Nil*_*ann 8 javascript jquery

我正在阅读jQuery的"插件/创作",虽然我已经写了一些jQuery-Plugins.现在我看到jQuery有一种特殊的方法来确定方法并调用:

(function( $ ){

  var methods = {
    init : function( options ) { // THIS },
    show : function( ) { // IS   },
    hide : function( ) { // GOOD },
    update : function( content ) { // !!! }
  };

  $.fn.tooltip = function( method ) {

    // Method calling logic
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    

  };

})( jQuery );
Run Code Online (Sandbox Code Playgroud)

我理解最终会发生什么的概念......但究竟是怎么回事?这部分让我感到困惑:

    // Method calling logic
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    }
Run Code Online (Sandbox Code Playgroud)

为什么Array.prototype.slide.call(argumetns, 1)?变量"参数"从何而来?任何简短或深入的解释都非常感谢.据说,这就是插件的编写方式......所以我想知道原因.

谢谢!

T.J*_*der 15

arguments

arguments是JavaScript语言的一部分.我很困惑于究竟你是当我第一次跑进它的方式; 这不仅仅是你.:-)它是每个函数中的自动局部变量,并且是一个类似于数组的结构,为您提供所有参数(参见规范的第10.6节),例如:

function foo() {
    var index;

    for (index = 0; index < arguments.length; ++index) {
        alert(arguments[index]);
    }
}
foo("one", "two"); // alerts "one", then alerts "two"
Run Code Online (Sandbox Code Playgroud)

当我说arguments像阵列一样,我的意思是 - 它不是一个数组.它对参数的引用是实时的(和双向的).例如:

function foo(namedArg, anotherNamedArg) {
    alert(namedArg === arguments[0]);        // alerts true, of course
    alert(anotherNamedArg === arguments[1]); // also alerts true
    namedArg = "foo";
    alert(arguments[0]);                     // alerts "foo"
    arguments[0] = "bar";
    alert(namedArg);                         // alerts "bar"
}
Run Code Online (Sandbox Code Playgroud)

请注意,在赋值时namedArg,结果会反映出来arguments[0],反之亦然.

arguments 真的很酷,但只有在需要时才使用它 - 一些实现通过不挂钩来加速调用函数,直到/除非函数实际上第一次尝试访问它,这可以减慢函数(非常轻微).

arguments它上面也有属性调用callee,它是对函数本身的引用:

function foo() {
    alert(foo === arguments.callee); // alerts true
}
Run Code Online (Sandbox Code Playgroud)

但是,最好避免使用arguments.callee有几个原因.一个原因是在许多实现中,它确实很慢(我不知道为什么,但是为了给你一个想法,如果你使用的话,函数调用开销会增加一个数量级arguments.callee).另一个原因是你无法在ECMAScript5的新"严格"模式下使用它.

(有些实现也有arguments.caller - 不寒而栗  - 但幸运的是它从未普及过,并且在任何地方都没有标准化[也不可能].)

slice呼叫并apply

关于

return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
Run Code Online (Sandbox Code Playgroud)

正在做的是使用该Array#slice方法将参数复制到数组中(减去第一个参数,这是要调用的方法),然后将结果数组传递给Function#apply它调用的函数实例上的函数.Function#apply使用给定this对象和作为数组提供的参数调用函数实例.代码不仅仅是arguments.slice因为(再次)arguments不是真正的数组,所以你不能依赖它拥有所有的数组函数,但是规范明确地说(在第15.4.4.10节中)你可以将Array.prototype.slice函数应用于任何像阵列一样的东西,这就是他们正在做的事情.

Function#apply并且Function#call也是JavaScript的内置部分(参见第15.3.4.3节和第15.3.4.4节).以下是每个简单示例:

// A function to test with
function foo(msg, suffix) {
    alert(this.prefix + ": " + msg + suffix);
}

// Calling the function without any `this` value will default `this`
// to the global object (`window` on web browsers)
foo("Hi there", "!"); // Probably alerts "undefined: Hi there!" because the
                      // global object probably doesn't have a `prefix` property

// An object to use as `this`
var obj = {
    prefix: "Test"
};

// Calling `foo` with `this` = `obj`, using `call` which accepts the arguments
// to give `foo` as discrete arguments to `call`
foo.call(obj, "Hi there", "!"); // alerts "Test: Hi there!"
      // ^----^-----------^---- Three discrete args, the first is for `this`,
      //                        the rest are the args to give `foo`

// Calling `foo` with `this` = `obj`, using `apply` which accepts the arguments
// to give `foo` as an array
foo.apply(obj, ["Hi there", "!"]); // alerts "Test: Hi there!"
            // ^---------------^---- Note that these are in an array, `apply`
            //                       takes exactly two args (`this` and the
            //                       args array to use)
Run Code Online (Sandbox Code Playgroud)

  • 像你这样的人是我爱这么多的原因. (2认同)