JavaScript ES6:测试箭头功能,内置功能,常规功能? [英] JavaScript ES6: Test for arrow function, built-in function, regular function?

查看:147
本文介绍了JavaScript ES6:测试箭头功能,内置功能,常规功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



Harmony wiki 指出:



< blockquote>

箭头函数就像内置函数一样,缺少.prototype 和[[Construct]]内部方法。所以new(()=> {})抛出一个TypeError,否则箭头就像函数


这意味着你可以测试箭头函数如:

 !(()=> {})hasOwnProperty(prototype)// true 
!(function(){})hasOwnProperty(prototype)// false

但是测试也将为任何内置函数返回 true ,例如 setTimeout Math.min



在Firefox中工作,如果您获得源代码,并检查它是否为本机代码,但它似乎不太可靠,也不可移植(其他浏览器实现,NodeJS / ioj) :

  setTimeout.toSource()。indexOf([native code])> -1 

小型GitHub项目 node-is-arrow-function 依赖于RegExp检查功能源代码,这不是那么整洁



编辑:我给了JavaScript解析器橡子尝试,似乎工作相当好 - 即使它是非常过分的。

  acorn =要求( ./橡子); 

函数fn_sample(a,b){
c =(d,e)=> D-E;
f = c( - a,b)*(b,a);
return f;
}

函数test(fn){
fn = fn || fn_sample;
try {
acorn.parse((+ fn.toString()+),{
ecmaVersion:6,
onToken:function(token){
if(typeof token.type ==object&&&&&&& ) b}
}
});
} catch(e){
console.log(Error,possible caused by [native code]);
console.log(e.message);
}
}

exports.test = test;


解决方案

相信与否...



在函数的字符串表示中测试=>的存在可能是最可靠的方式(但不是100%)。



显然,我们无法测试您提到的两种情况之一 - 缺乏原型属性和缺少 [[Construct]] ,因为这可能会导致误报主机或内置的缺少 [[Construct]]的对象或内置的对象 Math.floor JSON.parse 等)



然而,我们可以使用旧的 Function.prototype.toString 以检查函数表示是否包含=>。



现在,我一直推荐使用 Function.prototype.toString (所谓的函数反编译)由于其实现依赖和历史上不可靠的性质( Javascript中的函数反编译状态)。



但ES6实际上尝试执行规则(至少)内置的/>



  1. 如果Type(func)是Object并且是内置函数对象,或
    具有[[ECMAScriptCode]]内部插槽,则



    a。返回一个基于实现的String源代码的func。代表必须符合以下规则


...



toString表示要求:




  • 字符串表示形式必须具有FunctionDeclaration的语法FunctionExpression,GeneratorDeclaration,
    GeneratorExpession,ClassDeclaration,ClassExpression, ArrowFunction
    MethodDefinition或GeneratorMethod,具体取决于对象的实际
    特征。

    li>
  • 表示字符串中的空格,行终止符和分号的使用和放置是
    实现依赖。


  • 如果使用ECMAScript代码定义了对象,并且返回的字符串表示形式不是MethodDefinition或
    GeneratorMethod的形式,则表示形式必须如此,如果
    字符串被评估,在
    等价的词汇上下文中使用eval t用于创建原始对象的词汇上下文,
    将导致新的功能等效对象。在这种情况下,
    返回的源代码不能自由地提及
    没有被原始函数的源代码自由提及的任何变量,即使
    ,如果这些额外的名称最初在范围内。 / p>


  • 如果实现不能产生满足这些条件的源代码字符串,那么它必须返回一个字符串,eval将抛出
    a SyntaxError异常。 p>



我突出了相关的块。



箭头函数具有内部 [[ECMAScriptCode]] (您可以从14.2.17 - 箭头函数的评估到 FunctionCreate 跟踪 FunctionInitialize )。



这意味着他们必须符合 ArrowFunction语法

  ArrowFunction [In,Yield]:
ArrowParameters [?Yield] [no LineTer minator here] => ConciseBody [?In]

..这意味着他们必须在 Function.prototype.toString 的输出。



你显然需要确保=>遵循ArrowParameters,不仅仅是一些东西在FunctionBody中:

  function f(){return=> } 

关于可靠性 - 请记住,任何/所有引擎都可能不支持此行为无论何种原因,时刻和主持人对象的表现可能都是谎言(尽管规范的努力)。


Is there an elegant way to tell Harmony's slim arrow functions apart from regular functions and built-in functions?

The Harmony wiki states that:

Arrow functions are like built-in functions in that both lack .prototype and any [[Construct]] internal method. So new (() => {}) throws a TypeError but otherwise arrows are like functions

Which means, you can test for arrow functions like:

!(()=>{}).hasOwnProperty("prototype") // true
!(function(){}).hasOwnProperty("prototype") // false

But the test will also return true for any built-in function, e.g. setTimeout or Math.min.

It sort of works in Firefox if you get the source code and check if it's "native code", but it doesn't seem much reliable nor portable (other browser implementations, NodeJS / iojs):

setTimeout.toSource().indexOf("[native code]") > -1

The small GitHub project node-is-arrow-function relies on RegExp-checks against the function source code, which isn't that neat.

edit: I gave the JavaScript parser acorn a try and it seems to work quite okay - even though it's pretty overkill.

acorn = require("./acorn");

function fn_sample(a,b){
    c = (d,e) => d-e;
    f = c(--a, b) * (b, a);
    return f;
}

function test(fn){
    fn = fn || fn_sample;
    try {
        acorn.parse("(" + fn.toString() + ")", {
            ecmaVersion: 6,
            onToken: function(token){
                if(typeof token.type == "object" && token.type.type == "=>"){
                    console.log("ArrowFunction found", token);
                }
            }
        });
    } catch(e) {
        console.log("Error, possibly caused by [native code]");
        console.log(e.message);
    }
}

exports.test = test;

解决方案

Believe it or not...

Testing for presence of "=>" in string representation of a function is likely the most reliable way (but not 100%).

Obviously we can't test against either of 2 conditions you mentioned — lack of prototype property and lack of [[Construct]] as that might give false positives with either host objects or built-in ones that lack [[Construct]] (Math.floor, JSON.parse, etc.)

We could, however, use good old Function.prototype.toString to check if function representation contains "=>".

Now, I've always recommended against using Function.prototype.toString (so-called function decompilation) due to its implementation-dependent and historically unreliable nature (more details in State of function decompilation in Javascript).

But ES6 actually tries to enforce rules on the way (at least) built-in and "user-created" (for the lack of better term) functions are represented.

  1. If Type(func) is Object and is either a Built-in function object or has an [[ECMAScriptCode]] internal slot, then

    a. Return an implementation-dependent String source code representation of func. The representation must conform to the rules below.

...

toString Representation Requirements:

  • The string representation must have the syntax of a FunctionDeclaration FunctionExpression, GeneratorDeclaration, GeneratorExpession, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending upon the actual characteristics of the object.

  • The use and placement of white space, line terminators, and semicolons within the representation String is implementation-dependent.

  • If the object was defined using ECMAScript code and the returned string representation is not in the form of a MethodDefinition or GeneratorMethod then the representation must be such that if the string is evaluated, using eval in a lexical context that is equivalent to the lexical context used to create the original object, it will result in a new functionally equivalent object. In that case the returned source code must not mention freely any variables that were not mentioned freely by the original function’s source code, even if these "extra" names were originally in scope.

  • If the implementation cannot produce a source code string that meets these criteria then it must return a string for which eval will throw a SyntaxError exception.

I highlighted relevant chunks.

Arrow functions have internal [[ECMAScriptCode]] (which you can track from 14.2.17 — evaluation of arrow function - to FunctionCreate to FunctionInitialize).

This means they must conform to ArrowFunction syntax:

ArrowFunction[In, Yield] :
  ArrowParameters[?Yield] [no LineTerminator here] => ConciseBody[?In]

..which means they must have => in Function.prototype.toString's output.

You'll obviously need to ensure "=>" follows ArrowParameters and is not just something present in FunctionBody:

function f() { return "=>" }

As for reliability — remember that this behavior is/might not be supported by any/all engines at the moment and that host objects' representation might lie (despite specs efforts) for whatever reasons.

这篇关于JavaScript ES6:测试箭头功能,内置功能,常规功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆