闭包作用域面试题分析

let arr = [10.18, 0, 10, 25, 23];
arr = arr.map(parseInt);
console.log(arr);//[10,NaN,2,2,11]

分析: parseInt首先把第一项转换为字符串,然后看做X(2~36)进制,最后转换为十进制

  • parseInt(10.18,0)
    =>把’10’看做10进制转换为10进制 =>10
  • parseInt(0,1)
    =>NaN 第二个参数不在有效范围(2~36)内
  • parseInt(10,2)
    =>把’10’看做二进制,转换为十进制 => 0*2^0 + 1*2^1 => 2 *
  • parseInt(25,3)
    =>把’25’看做三进制,字符5不符合三进制,找到的只有字符2 =>2*3^0 =>2
  • parseInt(23,4) =>把’23’看做四进制,转换为十进制 =>3*4^0 + 2*4^1 =>3 + 8 =>11

答案 [10,NaN,2,2,11]


var a = 10,
    b = 11,
    c = 12;
function test(a) {
    a = 1;
    var b = 2;
    c = 3;
}
test(10);
console.log(a, b, c);//10 11 3
  1. 第一步:EC(G)变量提升(全局):var只声明不定义,function 声明+定义
    ↑ var a; var b; var c; function test(a){} [[scope]]:EC(G)(函数声明时候形成作用域,此时作用域为全局上下文)
    =>同时GO(window)中也设置了相关的属性
  2. 第二步:执行代码
    var a = 10,
    b = 11,
    c = 12; //=>全局a=10 b=11 c=12
    function test(a) {
    EC(test)私有上下文
    初始化作用域链:<EC(TEST),EC(G)>
    初始化THIS/ARGUMENTS
    形参赋值:a=10 [a是私有变量] =>形参赋值,形参属于私有变量
    变量提升:var b; [b是私有变量] =>变量提升有var 就是私有变量
    代码执行
    a = 1; //=>私有的a=1
    var b = 2; //=>私有的b=2
    c = 3; //=>全局的c=3 => c不是形参,也没有var所以是全局变量
    }
    test(10);
    console.log(a, b, c); //=>10 11 3 */

var a = 4;
function b(x, y, a) {
    console.log(a);
    arguments[2] = 10;
    console.log(a);
}
a = b(1, 2, 3);
console.log(a);//3 10 undefined

非严格模式

var a = 4; //全局a=4
function b(x, y, a) {

 * EC(B)私有上下文
 *   作用域链:<EC(B),EC(G)>
 *   初始化THIS
 *   初始化ARGUMENTS(函数内置实参集合[类数组]): {0:1,1:2,2:3,length:3}
 *   形参赋值:x=1  y=2  a=3  [x/y/a都是私有变量]
 * ==>在JS非严格模式下,函数中初始化ARGUMENTS和形参赋值完成后,浏览器会按照顺序把形参和ARGUMENTS中的每一项建立映射机制(一改都改)
 *      x -> arguments[0]
 *      y -> arguments[1]
 *      a -> arguments[2]
 *   变量提升:--	 
console.log(a); //=>3
arguments[2] = 10; //arguments[2]和a都会变为10(映射)
console.log(a); //=>10

}

a = b(1, 2, 3); //先把函数b执行,把函数执行的返回值(return的结果)赋值给全局a,如果不设置return,默认返回值是undefined 全局a=undefined
console.log(a); //=>undefined

严格模式

;
var a = 4;
function b(x, y, a) {
	"use strict"
    console.log(a);
    arguments[2] = 10;
    console.log(a);
}
a = b(1, 2, 3);
console.log(a);//3 3 undefined

“use strict”;
var a = 4;
function b(x, y, a) {
//严格模式下 x/y/a 和 arguments 是独立的,不会存在映射
console.log(a); //=>3
arguments[2] = 10;
console.log(a); //=>3
}
a = b(1, 2, 3);
console.log(a); //=>undefined */

实参和形参个数不一致

 function func(x, y, z) {
 	x = 100;
	console.log(arguments[0]); //=>100
	arguments[1] = 200;
	console.log(y); //=>200
	z = 300;
	console.log(arguments[2]); //=>undefined	
}
func(10, 20);//100 200 undefined

/* function func(x, y, z) {
/!*
* 初始化arguments:{0:10,1:20,length:2}
* 形参赋值:x=10 y=20 z=undefined
* ==>映射关系
* x -> arguments[0]
* y -> arguments[1]
* z ->
*!/
x = 100;
console.log(arguments[0]); //=>100

arguments[1] = 200;
console.log(y); //=>200

z = 300;
console.log(arguments[2]); //=>undefined

}
func(10, 20);



{
    function foo() {}
    foo = 1;
}
console.log(foo);//函数
//===========================
{
    function foo() {}
    foo = 1;
    function foo() {}
}
console.log(foo);  //1
//===========================
{
    function foo() {}
    foo = 1;
    function foo() {}
    foo = 2;
}
console.log(foo);//1

有大括号或判断体大括号变量提升处理

  • 新版本浏览器
    1、EC(G)全局变量提升遇到大括号,大括号中有function关键字,只声明不定义。
    2、代码执行:遇到大括号,当成块级私有上下文,再一次进行变量提升,此时function变量提升是声明+定义。
    3、私有块级作用域代码执行:遇到function,将function之前的操作映射给全局一份
{
    function foo() {}
    foo = 1;
}
console.log(foo);//函数

在这里插入图片描述

{
    function foo() {}
    foo = 1;
    function foo() {}
}
console.log(foo);  //1

在这里插入图片描述
{

    function foo() {}
    foo = 1;
    function foo() {}
    foo = 2;
}
console.log(foo);//1

在这里插入图片描述


var x = 5,
    y = 6;
function func() {
    x += y;
    func = function (y) {
        console.log(y + (--x));
    };
    console.log(x, y);
}
func(4);
func(3);
console.log(x, y);
// 11 6 13 10 6

var x = 5, //全局x=5
y = 6; //全局y=6
function func() {

 * EC(FUNC1)
 *   作用域链:<EC(FUNC1),EC(G)> 
 *   形参赋值:--
 *   变量提升:--

x += y; //x=x+y (x/y都是全局的) 全局x=11
func = function (y) { //全局func=BBBFFF000里层小函数 [[scope]]:EC(FUNC1)

	 * EC(FUNC2)
	 *   作用域链:<EC(FUNC2),EC(FUNC1)> 
	 *   形参赋值:y=3
	 *   变量提升:--
	
	console.log(y + (--x));
	//y私有的  x全局的  =>3+(--11) =>13 (2) 
	//=>全局的x=10
};
console.log(x, y); //=>11 6 (1)

}
func(4); //让外层大函数AAAFFF000执行
func(3); //让里层小函数BBBFFF000执行
console.log(x, y); //=>10 6 (3)


var a = 9;
function fn() {
    a = 0;
    return function (b) {
        return b + a++;
    }
}
var f = fn();
console.log(f(5));
console.log(fn()(5));
console.log(f(5));
console.log(a);

在这里插入图片描述


var test = (function (i) {
    return function () {
        alert(i *= 2);
    }
})(2);
test(5);

在这里插入图片描述


function fun(n, o) {
    console.log(o);
    return {
        fun: function (m) {
            return fun(m, n);
        }
    };
}
var c = fun(0).fun(1);
c.fun(2);
c.fun(3);

分析:

  • 返回对象是个地址,对象中有函数,函数又是一个地址,函数执行,形成上下文,最后返回的是最外层函数执行返回的结果(对象)。
  • 本题特别要注意作用域和作用域链

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值