Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

函数声明和函数表达式的区别 #10

Open
yanyue404 opened this issue Mar 1, 2018 · 0 comments
Open

函数声明和函数表达式的区别 #10

yanyue404 opened this issue Mar 1, 2018 · 0 comments

Comments

@yanyue404
Copy link
Owner

yanyue404 commented Mar 1, 2018

函数声明(funDeclaration)

无论在哪儿定义函数,只要是外层函数并且满足不被包裹,就都可以进行全局范围的调用

function foo() {}

在函数体内部的函数声明无法提升到全局,只能提升到函数体内顶部(块级作用域空间)

function test() {
  console.log(1);

  function test2() {
    console.log(2);
  }
}
test(); // 1
test2(); // Uncaught ReferenceError: test2 is not defined

函数体内部执行:

function test() {
  test2();
  function test2() {
    console.log(2);
  }
}
test(); // 2

在外部要想访问函数内部申明的函数,需要先return出来:

function test() {
  console.log(1);

  function test2() {
    console.log(2);
  }
  return {
    test2: test2
  };
}
test().test2(); // 2

函数表达式(funExpression)

函数表达式需要等到表达式赋值 完成 才可以

换言之使用var来声明函数,就会涉及到变量的声明提升,先拿出变量名定义为 undefined,再随着逻辑顺序进行赋值先定义,后使用

var foo = function () { }

demo1

Toast(); // hello world

showToast(); // shwoToast is not a function

var showToast = function() {
  console.log('123');
};
function Toast() {
  console.log('hello world');
}

在这里只需要把showToast提前就好了

demo2

主流浏览器解析,ie11+

var sayHello;
console.log(typeof sayHey); //=>undefined
console.log(typeof sayHo); //=>undefined
if (true) {
  function sayHey() {
    console.log('sayHey');
  }
  sayHello = function sayHo() {
    console.log('sayHello');
  };
} else {
  function sayHey() {
    console.log('sayHey2');
  }
  sayHello = function sayHo() {
    console.log('sayHello2');
  };
}
sayHey(); // => sayHey
sayHello(); // => sayHello

在花括号里面声明的函数在进行预解析时只会提升函数名,不会提升函数体,所以不管 if 条件是否为真,函数体都不会提升,永远是 undefined,接下来随着 if 条件判断进行解析赋值,当然是走 ture 方法。

ie9,ie10

var sayHello;
console.log(typeof sayHey); //=>function
console.log(typeof sayHo); //=>undefined
if (true) {
  function sayHey() {
    console.log('sayHey');
  }
  sayHello = function sayHo() {
    console.log('sayHello');
  };
} else {
  function sayHey() {
    console.log('sayHey2');
  }
  sayHello = function sayHo() {
    console.log('sayHello2');
  };
}
sayHey(); // => sayHey2
sayHello(); // => sayHello

在这里的 ie 将所有的函数声明进行了提升,从而由sayHey2替代了sayHey,函数表达式的在顺着条件判断进行了定义,执行为true的情况,进行赋值解析。

ie8

var sayHello;
console.log(typeof sayHey); //=>function
console.log(typeof sayHello); //=>function
if (true) {
  function sayHey() {
    console.log('sayHey');
  }
  sayHello = function sayHo() {
    console.log('sayHello');
  };
} else {
  function sayHey() {
    console.log('sayHey2');
  }
  sayHello = function sayHo() {
    console.log('sayHello2');
  };
}
sayHey(); // => sayHey2
sayHello(); // => sayHello

ie8 在这里处理的比较奇葩,正常的函数申明提升,但是却也将条件判断为假的情况进行了提升,我们看到typeof (sayHello)=>function

结论

由于函数声明提升的差异,想要在条件判断中定义不同的函数方法,应该采用定义函数表达式的方法,这样就在各个浏览器中拿到相同的函数方法,得到相同的结果。

var sayHello;
console.log(typeof sayHey); //=>undefined    ie8以下解析为function
console.log(typeof sayHo); //=>undefined
if (true) {
  var sayHey = function sayHey() {
    console.log('sayHey');
  };
} else {
  var sayHey = function sayHey() {
    console.log('sayHey2');
  };
}
sayHey(); // => sayHey
参考
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant