Javascript:给定的函数是否为空?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7960335/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 01:52:30  来源:igfitidea点击:

Javascript : is given function empty?

javascript

提问by Marek Sebera

Let's have a function call

让我们有一个函数调用

function doSomethingAndInvokeCallback(callback){
    // do something
    callback();
}

I can check if given argument is function if(typeof callback == 'function')

我可以检查给定的参数是否是函数 if(typeof callback == 'function')

How can I discover, if given callback function is function and isn't empty?

如果给定的回调函数是函数并且不为空,我如何发现?

like

喜欢

doSomethingAndInvokeCallback(function(){
    //nothing here
})

采纳答案by jfriend00

There is no totally reliable way to know if a function is empty because there are multiple kinds of functions in JS, some implemented with JS and some implemented with native code and you can't know for sure whether the function passed in does anything or not. If you want to limit the passed in function to only very simple JS functions, you could use the mechanisms outlined by other answers here (examining the source of the function). But, I would not recommend doing that in anything but a tightly controlled situation because there are lots of legal javascript ways to break that.

没有完全可靠的方法可以知道一个函数是否为空,因为 JS 中有多种函数,有些是用 JS 实现的,有些是用原生代码实现的,你无法确定传入的函数是否有任何作用. 如果您想将传入的函数限制为非常简单的 JS 函数,您可以使用此处其他答案概述的机制(检查函数的来源)。但是,我不建议在严格控制的情况下这样做,因为有很多合法的 javascript 方法可以打破这种情况。

I would suggest that you should change the contract of your function arguments and have the caller pass null or not pass anything (which will make the argument undefined) rather than an empty function. Then, it will be very clear whether they intend to have a function called or not. If they then pass an empty function instead of null or undefined, they are getting the behavior that the interface of the function specifies. The caller can choose the desired behavior and you can implement your function in a more failsafe manner.

我建议您应该更改函数参数的契约,并让调用者传递 null 或不传递任何内容(这将使参数undefined)而不是空函数。然后,很清楚他们是否打算调用一个函数。如果他们然后传递一个空函数而不是 null 或 undefined,他们将获得函数接口指定的行为。调用者可以选择所需的行为,您可以以更安全的方式实现您的功能。

Also, one of your main suppositions in your question is not quite right. You cannot safely use typeof x == "function"to determine if something is a function as that will not work reliably in some older versions of IE for some types of functions. If you want to learn how to detect if something is a function at all, you can learn from jQuery here (even if you're not using it). jQuery has a function it uses internally all the time called jQuery.isFunction()that returns a bool. It uses that mostly for testing arguments to see if a function was passed.

此外,您在问题中的主要假设之一不太正确。您不能安全地使用typeof x == "function"来确定某物是否是函数,因为对于某些类型的函数,它在某些较旧版本的 IE 中无法可靠地工作。如果你想学习如何检测某个东西是否是一个函数,你可以在这里学习 jQuery(即使你没有使用它)。jQuery 有一个函数,它一直在内部使用jQuery.isFunction(),它返回一个布尔值。它主要用于测试参数以查看是否传递了函数。

Internally, it calls:

在内部,它调用:

Object.prototype.toString.call(o)

and then examines the result. If the result has "Function" in it, then test test parameter is a function.

然后检查结果。如果结果中有“Function”,则 test 测试参数是一个函数。

So, using the same technique used in jQuery, you could build your own simple little isFunctionroutine like this:

因此,使用 jQuery 中使用的相同技术,您可以构建自己的简单小isFunction例程,如下所示:

function isFunction(test) {
    return(Object.prototype.toString.call(test).indexOf("Function") > -1);
}

Of course, if you have jQuery available, you could just use it's own version:

当然,如果你有可用的 jQuery,你可以使用它自己的版本:

jQuery.isFunction(o)

When there are questions with potential cross browser compatibility issues, I find it instructional to look at how one of the big libraries solves the issue, even if you aren't going to be using that library. You can be sure that the libraries have been vetted against many browsers so a technique they are using is safe. You sometimes have to unwrap all their own internal routines they may use to figure out what they're really doing (which was the case for this function), but you can save yourself a lot of legwork.

当存在潜在的跨浏览器兼容性问题时,我发现查看其中一个大型库如何解决该问题很有指导意义,即使您不打算使用该库。您可以确定这些库已经针对许多浏览器进行了,因此它们使用的技术是安全的。有时您必须解开它们可能使用的所有内部例程来弄清楚它们真正在做什么(此函数就是这种情况),但您可以为自己节省大量的跑腿工作。

You can see a working test bed for this here: http://jsfiddle.net/jfriend00/PKcsM/

你可以在这里看到一个工作测试台:http: //jsfiddle.net/jfriend00/PKcsM/

In modern browsers typeof fn === "function", but in older versions of IE, some functions give a typeof === "object"which is probably why jQuery uses this other method which does work in those older versions of IE.

在现代浏览器中typeof fn === "function",但在旧版本的 IE 中,某些函数给出了 atypeof === "object"这可能是 jQuery 使用这种在旧版本的 IE 中工作的其他方法的原因。

回答by James Sumners

It seems that you can define a function to retrieve the body of a function(1). I wrote a small (non-definitive) test of this:

似乎您可以定义一个函数来检索函数的主体(1)。我为此编写了一个小型(非确定性)测试:

http://jsfiddle.net/6qn5P/

http://jsfiddle.net/6qn5P/

Function.prototype.getBody =
  function() {
    // Get content between first { and last }
    var m = this.toString().match(/\{([\s\S]*)\}/m)[1];
    // Strip comments
    return m.replace(/^\s*\/\/.*$/mg,'');
  };

function foo() {
    var a = 1, b = "bar";
    alert(b + a);
    return null;
}

console.log(foo.getBody());
console.log(foo.getBody().length);

回答by pimvdb

One possibility is matching the .toStringresult against a regexp to get the function body, and then trim to check whether it has become an empty string:

一种可能性是将.toString结果与正则表达式匹配以获取函数体,然后修剪以检查它是否已成为空字符串:

var f = function foo()    { 


};

/^function [^(]*\(\)[ ]*{(.*)}$/.exec(
     f.toString().replace(/\n/g, "")
)[1].trim() === ""; // true

That ugly regexp does take care of spaces aroung named functions as well as extraneous spaces before the name and the opening brace. Spaces like in foo ()do seem to be removed, so there is no reason to check for those.

那个丑陋的正则表达式确实处理了命名函数周围的空格以及名称和左大括号之前的无关空格。像 infoo ()这样的空间似乎被删除了,所以没有理由检查这些。

回答by Mike Samuel

You can't do it for a host function, but for others, you can fairly reliably do

您不能为主机功能执行此操作,但对于其他功能,您可以相当可靠地执行此操作

function isEmpty(f) {
  return typeof f === "function" &&
      /^function[^{]*[{]\s*[}]\s*$/.test(
          Function.prototype.toString.call(f));
}

This isn't efficient, but major interpreters implement toStringfor functions in such a way that it works, though it will not work on some interpreters for some empty-ish functions

这效率不高,但主要的解释器toString以一种可以工作的方式实现函数,尽管它不适用于某些空函数的解释器

function () { /* nothing here */ }
function () { ; }
function () { return; }

回答by nrabinowitz

You mightbe able to get this from .toString():

可能可以从.toString()以下位置获取此信息:

var blank = function(){};
var f = function(){};
var f2 = function() { return 1; };

f.toString() == blank.toString(); // true
f2.toString() == blank.toString(); // false

but this is reallyprone to error:

但这真的很容易出错:

var blank = function(){};
var f = function(){ }; // extra space!
f.toString() == blank.toString(); // false

You could munge the strings a bit to try to overcome this, but I suspect this is very browser-dependent. I wouldn't actually try to do this in a production environment if I were you. Even if you normalize the whitespace, it still won't catch other no-op lines, including comments, useless varstatements, etc. To actually address these issues, you'd probably need a whole tokenizer system (or a crazy regex).

您可以稍微修改字符串以尝试克服此问题,但我怀疑这非常依赖于浏览器。如果我是你,我实际上不会尝试在生产环境中这样做。即使您将空格标准化,它仍然不会捕获其他无操作行,包括注释、无用var语句等。要实际解决这些问题,您可能需要一个完整的标记器系统(或疯狂的正则表达式)。

回答by svinto

In some implementation you can just do a toString() on the function and get it's content. Though it contains comments etcetera.

在某些实现中,您可以对函数执行 toString() 并获取其内容。虽然它包含评论等。

var foo = function(){ /* Comment */ };
alert(foo.toString());