形参和变量同名时
javascript的函数或者全局代码在执行前都有个预处理阶段。
预处理阶段可能涉及到的处理:形参赋值,变量声明提前、函数声明提前。
标识符重名问题主要是关注预处理的顺序。后处理的可能会覆盖先处理的结果。
根据测试案例得出处理顺序时:变量声明提前、形参赋值、函数声明提前。
所以如果,函数和形参同名的话,标识符会指向声明的函数。
下面举出实际的例子。
function fn(a){
alert(a); // hello
var a;
alert(a); // hello
}
fn('hello');
// 从声明提前来分析上面的代码
function fn(a){
/* 预处理阶段 */
var a; // 变量声明提前
var a = 'hello' // 形参赋值
/* 执行阶段 */
alert(a); // hello
alert(a); // hello
}
fn('hello');
function fn(a){
alert(a);
var a = 'hi';
alert(a);
}
fn('hello'); // --> 依次弹出hello和hi
// 从声明提前来分析上面的代码
function fn(a){
/* 预处理阶段 */
var a; // 变量声明提前
var a = 'hello'; // 形参赋值
/* 执行阶段 */
alert(a); // 弹出hello
a = 'hi';
alert(a); // 弹出hi
}
fn('hello');
function fn(a){
alert(a);
let a = 'hi'; // 报错 Uncaught SyntaxError: Identifier 'a' has already been declared
alert(a);
}
fn('hello');
// let是不允许声明重复的变量的 所以什么都不会弹出,形参变量名和函数局部变量重名了
function fn(a, b){
console.log(a, b);
var b = 'zhang'
function a() {}
console.log(a, b);
}
fn('hello', 'chen');
// 从声明提前来分析上面的代码
function fn(a, b){
/* 预处理阶段 */
var b; // 变量声明提前
var a= 'hello' // 形参赋值
var b = 'chen' // 形参赋值
function a () {} // 函数声明提前 (覆盖上面的a)
/* 执行阶段 */
console.log(a, b); // 打印function a(){} chen
b = 'zhang'
console.log(a); // 打印function a(){} zhang
}
fn('hello', 'chen');
function fn(a, b){
console.log(a, b);
var b = 'zhang'
function a() {}
console.log(a, b);
}
fn('hello', function c() {alert(1)});
// 从声明提前来分析上面的代码
function fn(a, b){
/* 预处理阶段 */
var b; // 变量声明提前
var a= 'hello' // 形参赋值
var b = function c() {alert(1)} // 形参赋值
function a () {} // 函数声明提前
/* 执行阶段 */
console.log(a, b); // 打印function a(){} function c() {alert(1)}
b = 'zhang'
console.log(a); // 打印function a(){} zhang
}
fn('hello', function c() {alert(1)});
function fn(a='你好'){
alert(a);
var a = 'hi';
alert(a);
}
fn(); // --> 依次弹出hello和hi
// 笔试题
var foo = {n:1};
(function (foo) {
var foo;
console.log(foo.n); // 1
foo.n = 3;
foo = {n:2};
console.log(foo.n) // 2
})(foo)
// 从声明提前来分析上面的代码
var foo = {n:1};
(function (foo) {
/* 预处理阶段 */
var foo; // 变量提升
foo = {n:1} // 形参赋值
/* 执行阶段 */
console.log(foo.n); // 1
foo.n = 3;
foo = {n:2};
console.log(foo.n) // 2
})(foo)
形参和函数名时
形参优先级高于函数名
function fn(fn){
alert(fn);
}
fn('hello'); // --> 弹出"hello"
形参和arguments同名时
形参优先级高于arguments
function fn(arguments){
alert(arguments);
}
fn('hello'); // --> 弹出"hello" 而不是[object Object]