jQuery迭代函数

Tyl*_*itt 3 javascript jquery expression function declarative

每个 jQuery迭代器函数都有类似这样的语法:

.each(function(index, element))
Run Code Online (Sandbox Code Playgroud)

这似乎意味着匹配此声明的函数必须采用2个参数.就像是:

function my_func(index, element){
  alert(index+":"+element);
}
Run Code Online (Sandbox Code Playgroud)

对我来说,这给出了两个可能的声明:

$("li").each(my_func);
Run Code Online (Sandbox Code Playgroud)

要么

$("li").each(function(index, element) {alert(index+":"+element);});
Run Code Online (Sandbox Code Playgroud)

第一个让我困惑,因为我没有看到indexelement传递给我my_func.在jQuery中是否有一些魔法知道它提供了my_func2个参数each

其次,如果我宣布了

var my_func= function(index, element){
  alert(index+":"+element);
}
Run Code Online (Sandbox Code Playgroud)

这会改变什么.我的理解是,第一个是声明式,第二个是表达式,但是,在这种情况下,它们的行为应该相同吗?

最后,each我看到的大多数实现都是这样的:

$("li").each(function(){alert(this)});
Run Code Online (Sandbox Code Playgroud)

each回调的所有参数都是可选的吗?

jfr*_*d00 5

将函数作为回调传递的方法

在这:

$("li").each(my_func);
Run Code Online (Sandbox Code Playgroud)

您只是将引用传递my_func.each()方法.每个方法本身都会在调用它时将两个参数传递给该函数.如果你想访问这两个参数,那么你可以在你自己的定义中将它们声明为参数my_func,但你不必这样做.无论你是否申报,论证都会在那里.

您可以通过多种不同方式声明my_func:

// somewhat normal way and you can easily access the index and element arguments
function my_func(index, element) {
     // code here
}

// if you don't need index and element, you don't need to declare them
// but they are still actually there and can be reached via the arguments object
function my_func() {
     // code here
     console.log(arguments[0]);   // index
}
Run Code Online (Sandbox Code Playgroud)

用.声明函数 var

和...之间的不同:

var my_func= function(index, element){
  alert(index+":"+element);
}
Run Code Online (Sandbox Code Playgroud)

function my_func(index, element){
  alert(index+":"+element);
}
Run Code Online (Sandbox Code Playgroud)

主要是时机之一.在第二个中,my_func定义为函数,只要它所在的javascript文件被定位并被解析,并且它定义的范围变为实时并且可用"好像"它在范围的最顶部被声明为它是定义的.这通常被称为"提升",其中定义被提升到定义它的范围的顶部.

在第一个,my_func不是函数UNTIL JS的那一行是在该javascript文件的正常执行流程中执行的.

除了时间,你可以互换使用这两个.如果个人更喜欢这个function xxx()表单,因为那时我不必担心函数是否在声明运行之前被调用 - 但这实际上是个人风格偏好.


你必须声明回调参数吗?

对于上一个问题,如果要使用它们,只需要声明回调的参数.在javascript中,函数是完全相同的函数,无论您是否使用参数声明它(在C++等语言中都不是这种情况),因此如果您想通过名称访问它们,则只需要声明它们.

javascript中的函数参数声明是可选的.您可以声明多于传递给函数的函数,并且可以声明少于传递给函数的函数.在javascript中都不会导致任何类型的错误.

假设你有这个代码:

 function callWithDelay(t, fn, arg1, arg2) {
     setTimeout(function() {
         fn(arg1, arg2);
     }, t);
 }
Run Code Online (Sandbox Code Playgroud)

使用它的预期方法是定义一个带有两个参数并将其作为fn参数传递的函数.

 function myFunc(msg, color) {
     var obj = document.getElementById("error")
     obj.innerHTML = msg;
     obj.style.color = color;
 }

 callWithDelay(2000, myFunc, "Both first and last name are required", "red");
Run Code Online (Sandbox Code Playgroud)

但是,您不必传递具有这些参数的函数.你可以这样做(通过arguments对象而不是通过名称访问参数):

 function myFunc() {
     var obj = document.getElementById("error")
     obj.innerHTML = arguments[0];
     obj.style.color = arguments[1];
 }

 callWithDelay(2000, myFunc, "Both first and last name are required", "red");
Run Code Online (Sandbox Code Playgroud)

或者,您可以传递一个甚至不需要这些参数的函数:

 function myFunc() {
     document.getElementById("error").style.display = "none";
 }

 callWithDelay(2000, myFunc);
Run Code Online (Sandbox Code Playgroud)

callWithDelay函数不关心您传递的函数引用类型.它几乎可以是任何功能.该callWithDelay函数将两个参数传递给它在调用它时传递给它的回调,但它完全取决于接收函数是否使用这些参数.在最后一个例子中,我callWithDelay在调用它时忽略了最后两个参数.当你离开一个参数(在调用列表的末尾)时,那个参数就是这样undefined.在javascript中undefined是合法的价值.因此,当我将它们从调用中移除时callWithDelay(2000, myFunc),它们就是undefined并因此undefined传递给myFunc回调作为它的两个参数.在这种情况下,由于没有使用这些参数,没有人关心它们undefined.


函数重载 - 检查传递的参数类型

在javascript中,您还可以检查传递给函数的参数类型,并相应地调整您的行为.例如,假设您有一个隐藏DOM元素的简单函数:

function hide(elem) {
    elem.style.display = "none";
}

// usage
var obj = document.getElementById("test");
hide(obj);
Run Code Online (Sandbox Code Playgroud)

此函数假定elem是一个DOM元素,并且仅在传递的内容时才起作用.但是,如果我们还想允许某人传递id一个元素,该怎么办呢?我们可以检查传递给hide它的参数,看看它是否是一个字符串,如果是这样,我们可以将它视为一个id值.

function hide(elem) {
    // if a string was passed, find the DOM object using that string as an id
    if (typeof elem === "string") {
        elem = document.getElementById(elem);
    }
    elem.style.display = "none";
}

// first usage
var obj = document.getElementById("test1");
hide(obj);

// second uage
hide("test2");
Run Code Online (Sandbox Code Playgroud)

现在,假设我们不仅要允许传递单个DOM元素,还要允许DOM元素数组,以便该函数可以对数组中的每个DOM元素进行操作.

function hide(elem) {
    // if a string was passed, find the DOM object using that string as an id
    if (typeof elem === "string") {
        document.getElementById(elem).style.display = "none";
    } else if (typeof elem === "object" && Object.prototype.toString.call(elem) === "[object Array]") {
        // an array was passed
        for (var i = 0; i < elem.length; i++) {
            elem[i].style.display = "none";
        }
    } else {
        // only a single DOM element was passed
        elem.style.display = "none";
    }
}

// usages
hide(obj);
hide([obj1, obj2, obj3]);
hide("test");
Run Code Online (Sandbox Code Playgroud)