函数的预处理

346 阅读2分钟

console.log(a)  // 输出函数
var a = 5
function a () {}

function fn(a,b,a){
console.log(a);//function a(){}
console.log(arguments[0]);//1
console.log(arguments[2]);//function a(){}
function a(){
}
var a=5;
}
fn(1,2,3);

函数预处理:函数开始运行时会创建跟参数名相同的变量并赋值再和arguments对象产生引用关系。

预处理阶段 function 优先级最高 预处理阶段发生冲突的变量名,会被优先级高的忽略掉。

函数读取中 arguments 优先级是最高的 比function 还要高。

(1)函数参数名称重复

function fn(a,b,a){
        console.log(a)
        var a=10;
        console.log(arguments[0]);
        console.log(arguments[1]);
        console.log(arguments[2]);
}
 fn(1,2,3); // 会输出什么?

函数fn(),arguments[0] 优先级是最高,此时输出1,由于函数预处理,所有此时a已经被重新赋值变成了10

预处理阶段将变量保存在window域:会产生变量提前和函数声明提前的效果。

window{
    fs : 指向函数,
    as : undefined,
    gs : undefined
}

在执行阶段window域的情况

window{
    f : 指向函数,
    a : 1,
    b : 2,
    g : 指向函数
}

//预处理阶段:声明提前
onsole.log('as',a)
console.log('fs',f)
console.log('gs',g)
// console.log('bs',b)
var a = 1;
     b = 2;
function f (){console.log("11");}
var g = function(){console.log("22");};
// 执行阶段
console.log('as1',window.a)
console.log('fs1',window.f)
console.log('gs1',window.g)
console.log('bs1',window.b)

如果声明发生冲突。那么在预处理的时候遵循两个规则:

a. 先扫描函数,再扫描var声明的变量;

b. 如果与之前的声明发生冲突的是函数,则覆盖;如果是var声明的变量,则忽略

// 后者覆盖前者
console.log(f); 
function f() {console.log('1')}
function f() {console.log('2')}

// 函数优先,后者忽略
console.log(f); // 执行函数
var f = 1
function f() {console.log('2')}
var f = 4

console.log(abc) // undefined
var abc = 0 ; 
var abc = function(){console.log('1')}

(2)方法不允许有多个命名相同的形参

//正确写法
// 此写法是非严格模式,在预处理阶段函数内部会优先创建和参数相同的变量名,赋值和相同参数名的覆盖操作。
// 当然也不推荐这样写
function fn(a, a, y){console.log(a);}
fn(2,3,4);

// 错误写法 Uncaught SyntaxError
// 这种写法视为严格模式'use strict'
function fn(a, a, y = 2){console.log(a);} 
fn(2,3);

(3) 严格模式和非严格模式

严格模式下:形参与arguments完全独立

'use strict';
function showValue(value){
    value = "Foo";   // 形参和变量同名:赋值和覆盖,同时也是局部变量
    values = "Foo";  // 全局变量 
    console.log(value); //"Foo"    
    console.log(arguments[0]); //非严格模式:"Foo";严格模式:"Hi"
}
showValue("Hi");
console.log('values ', values ) // 访问全局变量
console.log('value', value) // 报错

严格模式链接