几道JS闭包题目

function fun(n,o) {
   console.log(o);
   return {
      fun:function(m){
      return fun(m,n);
    }
  };
}


三个fun函数是一样的吗?


第一个fun是具名函数,可通过fun.name得到'fun',即函数名;返回值是一个对象字面量表达式,属于一个新的Object;

对象字面量里有一个叫fun的属性,该属性是一个匿名函数表达式,属于新创建的函数,所以第一个和第二个fun函数是不一样的;

匿名函数表达式又返回一个fun函数,我们可以知道这个函数肯定不是新创建的,那么它是指的第一个还是第二个呢?

这就涉及到函数作用域链的问题了。

全局环境中有一个函数fun(),fun()的局部环境中没有变量,所以第三个fun在局部环境中查询不到,就会向上查找,即在全局环境中找到。

所以第三个和第一个是同一个。

var name = "The Window";
var object = {
    name: "My Object";
    getName: function(){
        return function(){
            return this.name;
        };
    }
};
alert(object.getName()()); //"The Window"

每个函数在被调用时都会自动取得两个特殊变量:this和arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远不可能直接访问到外部函数中的这两个变量。

var name = "The Window";
var object = {
    name: "My Object";
    getName: function(){
        var that = this;  //把外部作用域中的this对象保存在一个闭包能够访问到的变量中,就可以让闭包访问该对象了
        return function(){
            return this.name;
        };
    }
};
alert(object.getName()()); //"My Object"


function createFunction(){
    var result = new Array();
    
    for(var i=0;i<10;i++){
        result[i] = function(){
            return i;
        };
    }
    
    return result;
}

这个函数会返回一个函数数组,表面上看,每个函数都应该返回自己的索引值,但实际上每个函数都返回10。因为每个函数的作用域链中都保存这createFunction()函数的活动对象,所以它们引用的都是同一个变量i。当createFunction()函数返回后,变量i的值是10,此时每个函数都引用者保存变量i的同一个变量对象,所以在每一个函数内部i的值都是10.

function createFunction(){
    var result = new Array();
    
    for(var i=0;i<10;i++){
        result[i] = function(num){
            return function(){
                return num;
            };
        }(i);
    }
    
    return result;  //可以返回各自不同的数值了
}
闭包是指在一个函数内部定义的函数可以访问外部函数的变量和参数,即使外部函数已经执行结束。闭包形成一个封闭的作用域,保留了外部函数的变量和环境。这种特性使得闭包可以解决诸如变量私有化、保存变量状态等问题。 闭包的应用场景有很多,例如在异步编程中,可以使用闭包来保持状态,避免变量提升导致的错误;在模块化开发中,可以使用闭包来实现私有变量和方法的封装。但闭包也有一些注意事项,比如会占用内存,造成内存泄漏;还可能导致变量无法被垃圾回收,影响性能。 原型链是JavaScript中实现继承的机制。每个JavaScript对象都有一个内置的属性__proto__指向它的原型对象,原型对象又有自己的__proto__,形成了原型链。当访问对象的属性或方法时,会先在对象本身查找,如果找不到则沿着原型链向上查找,直到找到或者到达原型链的末尾(即null)。 原型链的好处是可以节省内存,将公共的属性和方法定义在原型对象中,所有实例对象共享这些属性和方法;还可以实现继承,子类对象的原型对象可以指向父类对象,从而共享父类的属性和方法。 原型链的缺点是只能继承父类的实例属性和方法,不能继承构造函数中的私有属性和方法;还有可能出现多个子类实例共享同一个父类实例的情况,导致数据共享的问题。 为了解决原型链继承的缺点,ES6引入了class关键字,可以更方便地实现面向对象编程,并且支持super关键字调用父类的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值