【问题标题】:How to assign a function with parameters without executing it in javascript?如何在不在javascript中执行的情况下为函数分配参数?
【发布时间】:2016-05-04 05:56:25
【问题描述】:

我的目标是在使用 javascript 单击按钮元素时更改它们的边框样式。我创建了一个函数 setBorder 并分配给所有按钮元素上的 onclick 事件:

function setBorder(myobj) {     
            myobj.style.borderStyle = "inset";
        }  
var menubtn = document.getElementById("menu_btn");
menubtn.onactive = setBorder(menubtn);

这里的问题是边框样式在页面加载后立即更改,因为在解析 javascript 时,由于括号 () 而执行函数 setBorder()。我认为的另一种选择是:

function setBorder() {      
            this.style.borderStyle = "inset";
        }  
var menubtn = document.getElementById("menu_btn");
menubtn.onactive = setBorder;

我以为this 会拿走menubtn 的对象——但这并没有发生。为什么this 不拿对象menubtn

我认为有一种方法可以将setBorder 链接为所有按钮元素的原型对象。原型对象将有一个函数func_SetBorder 作为它的属性。然后我们可以将func_setBorder 称为:

menubtn.onclick = menubtn.func_setborder;

【问题讨论】:

    标签: javascript html


    【解决方案1】:

    此解决方案通过使用function closure 来实现您所寻找的。​​p>

    var buttons = [ ... ];   // An array containing the buttons
    
    for (let b of buttons) {
      b.onactive = onActive(b);
    }
    
    function onActive(button) {
      return function () {
        button.style.borderStyle = 'inset';
      }
    }
    

    【讨论】:

    • 假设我在一个网站上有 23 个按钮,那么我将不得不编写 23 次函数定义。有没有什么方法可以只定义一次并且可以调用 23 次?
    • 所以诀窍是在return语句中使用该函数。所以当解析器看到b.onactive = onActive(b)——它会执行onActive(b),它只是将函数返回给b.onactive
    【解决方案2】:

    好吧,在 JavaScript 中,当您在 this 的函数内部使用 this 关键字时,它将指向您调用函数的对象。所以,你有这样的功能

    function myFunc() {
        this.do_smth;
    }
    

    然后你调用它:my_obj.myFunc(),然后,在你的myFunc 内部,this将指向my_obj

    假设你想用另一个对象调用你的函数:

    obj_foo.myFunc()
    

    在这种情况下,您的函数内部的this 将指向obj_foo

    如果您想用不同的对象调用您的函数(但您必须确保您的对象具有相同的属性),最好使用call/applybind

    bind 会对你的函数说“这是你应该使用的范围”。但是在使用this 的情况下,您应该始终将您的函数绑定到不同的对象。更漂亮和安全的方法是使用call/apply。您还应该每次都使用call/apply 调用您的函数,就像使用bind 一样,但它看起来更好。

    所以,你的代码应该是这样的:setBorder.call(menubtn)

    【讨论】:

    • 似乎有人对您的答案投了反对票而没有回答。无论如何感谢您的解释。
    • 最后一行不正确。它正在调用函数,并将未定义的返回值分配为回调。
    • @user31782,希望对您有所帮助:)
    • 但是现在setBorder.call(menubtn) 将如何通过onactive 事件执行?
    • @user31782 试试这个menubtn.onactive = function() { setBorder.call(menubtn) }
    【解决方案3】:

    您想要的是绑定或绑定参数。 Javascript 提供了一种绑定函数的本机方式。如果你只想绑定参数,你可以使用here引用的这个方法:

    Function.prototype.arg = function() {
        if (typeof this !== "function")
            throw new TypeError("Function.prototype.arg needs to be called on a function");
        var slice = Array.prototype.slice,
            args = slice.call(arguments), 
            fn = this, 
            partial = function() {
                return fn.apply(this, args.concat(slice.call(arguments)));
    //                          ^^^^
            };
        partial.prototype = Object.create(this.prototype);
        return partial;
    };
    

    你会这样使用它:

    function setBorder(myobj) {     
                myobj.style.borderStyle = "inset";
            }  
    
    var menubtn = document.getElementById("menu_btn");
    menubtn.onactive = setBorder.arg(menubtn);
    

    或者:

    function setBorder() {     
                this.style.borderStyle = "inset";
            }  
    
    var menubtn = document.getElementById("menu_btn");
    menubtn.onactive = setBorder.bind(menubtn);
    

    【讨论】:

      【解决方案4】:

      CSS

      #menuBtn:active{
         border-style:inset;
      }
      

      Javascript

      您应该尝试eventlistener 属性

      menubtn.addEventListener("mousedown", setBorder);

      menubtn.addEventListener("mouseup", removeBorder);

      setBorderremoveBorder 函数中,您可以使用this

      【讨论】:

      • 这不起作用。为什么this 现在会在 setBorder 中工作?
      • 而不是active 监听click 事件,这将完美地工作。我已经用相同的方式编辑了我的答案
      • 是的,现在可以了。我也明白了为什么this 现在使用该对象,因为正如Andrew 解释的那样,它是用对象obj.function 调用的。
      • 实际上我希望为 active 状态设置边框样式。 click 事件使边框永远保持样式。 menubtn.addEventListener("active", setBorder); 存在吗?我可以在这里使用active 状态吗?我也不能接受你的回答,因为你刚刚给出了另一种实现结果的方法。我正在寻找解释性答案。 +1
      • 您可以通过在javascript中使用focusblur事件来实现这一点。但是 CSS 有一个很好的解决这个问题的方法。我已根据您的需要编辑了答案
      【解决方案5】:

      将它分配给一个变量。

      var functionName = function () { 
         //things
      }
      

      【讨论】:

      • 在此之后我将如何调用该函数?
      【解决方案6】:

      如果你想让thissetBorder函数中成为menubtn,你需要绑定它:

      menubtn.onclick = setBorder.bind(menubtn)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-29
        • 2013-07-04
        • 2011-12-13
        相关资源
        最近更新 更多