JS面试题

题目一:

{
    function test() {
        let n = 4399;
        function add() {
            n++;
            console.log(n);
        }
        return {n:n,add:add};
    };
    let re = test();
    let re2 = test();
    re.add();// 4400
    re.add();// 4401
    console.log(re.n);//4399
    re2.add()//4400
}

输出结果:4400 4401 4399 4400。
第一步:let re = test();这一句就已经把test函数执行了一遍,然后re保存的就是:{n:4399,add:function add(){}}。

第二步:let re2 = test(),这一句会重新执行一次test函数,re2保存的就是一个新的{n:4399,add:function add(){}}。

第三步:re.add(),就是直接调用函数中的add函数(这里形成了闭包,test中的n变量就不会被垃圾回收机制回收掉),对n进行加1,然后输出4400。
当再次调用re.add(),这时候的n还是同一个n,n在第一次调用的时候就变成了4400,然后再次调用,变成4401,然后打印re.n,这时候的n在let re = test()的时候就已经保存了,且后面调用add并没有对这个n进行修改。

第四步:最后re2.add(),就相当于第一次运行re.add。所以输出4400

题目二:

{
    function F(){}
    Object.prototype.a = function () { };
    Function.prototype.b = function () { };
    let f = new F();
    console.log(f.a);//[Function (anonymous)]
    console.log(f.b);//undefined
}

首先先去了解原型链的继承关系,每个实例都有__ proto__属性,所以构造函数都有prototype属性,且每个实例的__ proto__属性和创建它的构造函数的prototype属性指向同一个对象。
f.a会从自身寻找到原型链的最顶端(null)。

F相当于是Function的实例,F是Function的实例,那么F.__ proto__ ==Function.prototype,但是f是构造函数F的实例,所以f.__ proto__属性 == F.prototype,F.__ proto__属性才等于Function.prototype,所以Function.prototype属性并没有在f的原型链上。

f.__ proto __ .__ proto __ == Object.prototype//返回true,所以a是在f的原型链上,但是Function不在。

题目三:

{
    let myObject = {
        foo: "bar",
        func: function () {
            let self = this;
            console.log(this.foo);
            console.log(self.foo);
            (function () {
                console.log(this.foo);
                console.log(self.foo);
            })()
        }
    }
    myObject.func();
}

输出结果:bar bar undefined bar
首先func函数中的this的指向就是谁调用它就指向谁。
myObject.func(),myObject就是调用func的上下文,然后把this赋值给了self,所以前两句都能访问到foo属性,但是立即执行函数中的this是指向全局的,self还是继承外层的self,所以输出 bar bar undefined bar。

题目四:

{
    function foo() {
        let i = 0;
        return function () {
            console.log(i++);
        }
    }
    let f1 = foo();
    let f2 = foo();
    f1();
    f1();
    f2();
}

输出结果:0 1 0
let f1 = foo(); 这一句执行过后,f1就保存返回的函数,然后f1()就是执行一次该函数,对n进行打印,log(i++),首先先打印i,再对i进行++,当第二次调用f1()之前,i已经是1了,然后再执行该函数,打印1,再加一。
然后f2就相当于又是一个新的foo函数执行得到的函数,f1不等于f2。
所以f2(),就输出0.

题目五:

{
    (function () {
        var x = foo();
        var foo = function foo() {
            return "foo"
        }
        return x;
    })()//类型错误,foo不是一个函数。
}

函数声明会被提升,但是函数表达式却不会被提升。
首先会进行var关键字声明的变量,会进行变量提升,var x = foo(),这里的foo在下面用var关键字进行了声明,所以会进行变量提升,foo就是undefined,所以undefined()就直接报错。

题目六:

{
    var name = "World";
    (function () {
        var name;
        if (typeof name == 'undefined') {
            name = "Jack";
            console.log("Goodbye "+name);
        } else {
            console.log("Hello "+name);
        }
    })()
}

输出结果:Goodbye Jack
在函数作用域中,首先会在内部寻找变量是否存在,不存在然后再去外层寻找,所以这里的name声明了还没定义,所以就是undefined。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坦淡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值