首页 > js 公有方法通过 new Function 方式调用私有方法的问题?

js 公有方法通过 new Function 方式调用私有方法的问题?

var Circle = function() {
   var pi = function(){
       return '3.14159';
    };

   this.area = function( str) {
       console.log(eval(str)());    //能正确调用
       //提示pi is not defined,该如何调用??
       console.log(new Function('return '+str).call());
   };
}
var c= new Circle();
c.area('pi');

new Function

Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was called
new Function生成的函数对象不会形成闭包结果,它们总是在全局作用域下生成,也就是这个函数对象是挂在全局对象下的。

eval

eval输入参数是一个字符串信息,JS在运行时通过编译器会编译字符串表示的代码,形成的作用域和直接写代码的效果相同

new Function('return '+str).call();语句中new Function('return '+str)创建了一个函数对象,call方法调用这个函数对象。如果作用域正确,调用的结果是返回一str表示的对象的字符串表示
如果str标示在JD解析器解析后是一个函数对象并且你想调用它,那么需要再调用一次

new Function('return '+str).call()();

new Function('return '+str)()();

一定要调用new Function,那么可以使用如下方式,供参考

var Circle = function() {
   
   var pi = function(){
       return '3.14159';
    };

   this.area = function( str) {
       console.log(eval(str)());    //能正确调用
       console.log(new Function(str,'return '+str).call(null,pi)());
   };
}
var c= new Circle();
c.area('pi');

var Circle = function() {
   var pi = function(){
       return '3.14159';
    };

   this.area = function( str) {
       console.log(eval(str)());    //能正确调用
       //提示pi is not defined,该如何调用??
       //console.log(new Function('return '+str).call());
       console.log(pi);
   };
}
var c= new Circle();
c.area('pi');

如果只是想调用的话,可以这样写.


上面已经解释了为什么访问不到,我这里按照你的要求给出个方案,看看是不是你要的

function MyClass() {
    var privateMethods = {};

    function m1(a, b) {
        console.log('this is a private method in MyClass, m1', a, b);
    }

    function m2(a, b) {
        console.log('this is a private method in MyClass, m2', a, b);
    }

    privateMethods = {
        m1: m1,
        m2: m2
    };

    this.invokePrivateMethod = function(methodName) {
        if(typeof privateMethods[methodName] == 'function') {
            privateMethods[methodName].apply(null, Array.prototype.slice.call(arguments, 1))
        } else {
            throw new Error('there is no such a private method named ' + methodName);
        }
    };
}

// example
var myClass = new MyClass();
myClass.invokePrivateMethod('m');  // => throw error
myClass.invokePrivateMethod('m1', 'arg1', 'arg2'); // invoke m1 with parameters
myClass.invokePrivateMethod('m2'); // invoke m2 without parameters

原因:通过new Function生成的函数对象的外部词法环境是全局环境,而不是包裹它的那个函数的词法环境。所以它不能访问到外层函数(以及外层函数的外层函数)中定义的变量。

15.3.2.1 new Function

Pass in the Global Environment as the Scope parameter

换句话说,它的“作用域链”绕过了外层的n层函数,直接链接到了全局作用域。

【热门文章】
【热门文章】