• 解决掉你心中 js function与Function的关系的疑问


    前言

    在网上有很多关于js function 与 Function直接关系的文章。
    但是我感觉过于抽象化了,那么如何是具体化的解释?
    正文部分为个人理解部分,如有不对望指出。

    正文

    <script>
    	if((function(){}).constructor === Function)
    	{
    		console.log(true);
    	}
    </script>
    

    我写了一段这个代码,答案为true。
    这就是function 与 Function的关系。
    看下Function的定义:

    Function 构造函数创建一个新的 Function 对象。直接调用此构造函数可用动态创建函数,但会遭遇来自 eval 的安全问题和相对较小的性能问题。然而,与 eval 不同的是,Function 构造函数只在全局作用域中运行。
    

    然后还给出了这样一个结论:

    每个 JavaScript 函数实际上都是一个 Function 对象。
    

    重新理解一下,Function的定义。

    第一句话很好理解,就是可以创建一个Function对象。第二句好也好理解,就是会有安全漏洞和性能问题,详细部分可看eval的安全问题,至于为什么低效,官方解释是:因为使用后者创建的函数是跟其他代码一起解析的。
    第三句话,什么叫"Function 构造函数只在全局作用域中运行"?

    var func = new Function("alert(x+y);");
    var test = function () {
    	var x=1,y=2;
    	func();
    	eval("x+y");
    }
    

    就是func()运行会报错。而eval("x+y")是成功的。
    因为func()是在全局作用域中运行。
    如果是这样:

    var x=1,y=2;
    var func = new Function("alert(x+y);");
    var test = function () {
    	var x=1,y=2;
    	func();
    	eval("x+y");
    }
    
    test();
    

    那么会弹出3;
    当然这里说eval是在局部变量中运行也比较绝对,因为eval的引用变量是在全局中运行的。

    var global=eval;
    global("x+y");
    

    这样就在全局中运行,好吧,这不是该篇的重点。
    那么这种Function 对象和申明函数有什么区别呢?前面已经说明了,Function对象是在全局中运行,而声明函数是在局部中运行。
    我找了一个例子:

    var x = 10;
    
    function createFunction1() {
        var x = 20;
        return new Function('return x;'); // 这里的 x 指向最上面全局作用域内的 x
    }
    
    function createFunction2() {
        var x = 20;
        function f() {
            return x; // 这里的 x 指向上方本地作用域内的 x
        }
        return f;
    }
    
    var f1 = createFunction1();
    console.log(f1());          // 10
    var f2 = createFunction2();
    console.log(f2());          // 20
    

    看到这里,以为结束了?下面是本文的核心思想部分。
    我们如何才能够,用function的方式建立出Function对象的效果?或者说我们如何模拟new Function() 到底发生了什么。

    var x=1,y=2;
    var func = new Function("alert(x+y);");
    var func1= function ()
    {
    	alert(x+y);
    }
    console.log(func);
    console.log(func1);
    

    打印出来func,是一个匿名的函数。
    匿名函数自带是闭包效果,在这里我似乎找到了答案,现在我们就来模拟出new Function();

    function main() {
    	var x = 5;
    	var y = 6;
    	 FunctionObj = function () {
    		alert(x + y);
    	};
    
    	function func() {
    		var x = 1;
    		var y = 2;
    		var Newfunc = FunctionObj;
    		Newfunc();
    	}
    	func();
    }
    main();
    FunctionObj();
    

    弹出的结果是11,另一个弹出的还是11;
    在这里我假设启动的是main主函数,x与y是全局变量。
    然后在func中的:

    var func = FunctionObj;
    func();
    

    假设为new Function(),也就是说去假设构建一个Function 对象。
    这样实现的其实就是在全局变量中创建了FunctionObj变量,然后赋值给了func,然后再执行func的时候自然就在main变量中了,因为匿名函数本身就闭包。
    对应为:

    var x=5;
    var y=6;
    function func()
    {
    	var x=1;
    	var y=2;
    	var NewFunc= new Function("alert(x+y)");
    	NewFunc();
    }
    func();
    

    继续变化一下,模拟Function 做了什么:

    var x=5;
    var y=6;
    function func()
    {
    	var x=1;
    	var y=2;
    	var NewFunc= Functionsimulation();
    	NewFunc();
    }
    function Functionsimulation()
    {
    	 var global=eval;
    	 return eval("(function(){return function(){alert(x+y)}})()");
    }
    func();
    

    弹出的结果依然是:11;

    总结

    回过头来,再看一下这段话:

    每个 JavaScript 函数实际上都是一个 Function 对象。
    

    new Function 只是将匿名包,绑定到了一个全局变量了,这样它的this永远固定,运行时,永远是在全局中运行。
    至于声明函数,因为是动态的运行,所以我们访问的以局部优先,也可以理解为绑定的为局部变量。
    以上是个人理解,如有不对望指出。

  • 相关阅读:
    ABAP开发者上云的时候到了
    1074. 宇宙无敌加法器(20)
    1073. 多选题常见计分法(20)
    1072. 开学寄语(20)
    1071. 小赌怡情(15)
    1049. Counting Ones (30)
    1047. Student List for Course (25)
    1044. Shopping in Mars (25)
    1043. Is It a Binary Search Tree (25)
    1040. Longest Symmetric String (25)
  • 原文地址:https://www.cnblogs.com/aoximin/p/12369693.html
Copyright © 2020-2023  润新知