本人所有文章均為學習過程中的總結,不同程度地參考了互聯網上其他的文章,如果不正懇請指出,共同進步
變量提升
JS代碼的執行分為兩個階段
預解析階段
- 變量名和函數聲明提升至當前作用域的最上方(只提升聲明,不提升賦值)
執行階段
- 按照從上至下的順序執行語句
注意:
- 變量與函數同名時,只提升函數,不提升變量
- 函數同名時,都提升,后面的函數覆蓋前面的函數
- 函數表達式只會提升變量名,賦值語句在執行階段按照順序執行
- 變量提升是分塊的<script></script>
- 條件是函數聲明能否被提升取決于瀏覽器,不推薦使用if(true){function(){}};
實例:
//js中沒有塊級作用域的說法,大括號并不會創建一個作用域
for(var i=0;i<5;i++){
console.log(i);//0 1 2 3 4
}
console.log(i);//5 for循環外部依舊可以訪問到i
只有函數能夠創建作用域
變量提升是分作用域的
函數與變量同名只提升函數 但是變量賦值還是要執行的
代碼:
var num=10;
function num(){
console.log(123);
}
num();
預編譯
function num(){
console.log(123);
}
num=10;
num();//is not a function
函數與函數同名全部都會提升,但會以函數聲明順序進行覆蓋,后面覆蓋前面的
代碼:
function f1(){
console.log('first');
}
function f1(){
console.log('last');
}
預編譯:
function f1(){
console.log('last')
}
函數表達式與變量提升方式相同,變量賦值不會被提升,但變量聲明會提升
代碼:
f1()//undefined
var f1=function(){
console.log('f1');
}
預編譯:
var f1;//提升
f1();//調用 undefined
f1=function(){//賦值
console.log('f1');
}
代碼:
function foo() {
var num = 123;
console.log(num); //123
}
foo();
console.log(num); //is not defined
預編譯:
function foo() {
var num;
num = 123;
console.log(num); //?123
}
foo();
console.log(num); //is not defined
//is not defined 沒有定義
//undefined 定義了沒有賦值
代碼:
var scope = "global";
foo();
function foo() {
console.log(scope); //undefined
var scope = "local";
console.log(scope); //local
}
預編譯:
var scope;
function foo(){
var scope;
console.log(scope);
scope = "local";
console.log(scope);
}
scope = "global";
foo();
//in 關鍵字 判斷某個對象中是否有某個屬性
代碼:
function f1(){
if("a" in window){
var a = 10;
}
alert(a);//undefined
}
f1();
預編譯:
function f1(){
var a;
if("a" in window){
a = 10;
}
alert(a);//undefined
}
f1();
代碼:
if("a" in window){
var a = 10;
}
alert(a); //10
預解析:
var a;
if("a" in window){
a = 10;
}
alert(a);
代碼:
if(!"a" in window){
var a = 10;
}
alert(a); // undefined
預解析:
var a;
if(!"a" in window){
a=10;
}
alert(a);
代碼:
var foo = 1;
function bar() {
if(!foo) {//此處提升了foo但是是undefined 判斷語句會轉為!undefined -->true
var foo = 10;
}
alert(foo); //10
}
bar();
預解析:
var foo;
function bar(){
var foo;//undefined
if(!foo) {//!undefined --> ture
foo = 10;//10
}
alert(foo); //10
}
foo = 1;
bar();
代碼:
function Foo() {
getName = function(){ alert(1); };
return this;
}
Foo.getName = function() { alert(2); };
Foo.prototype.getName = function(){ alert(3); };
var getName = function() { alert(4); };
function getName(){ alert(5); }
Foo.getName(); //2
getName(); //4
Foo().getName(); //1
getName(); //1
new Foo.getName(); //2
new Foo().getName(); //3
new new Foo().getName(); //3
預解析:
function Foo() {
getName = function(){ alert(1); };
return this;
}
var getName;
function getName(){ alert(5); }
Foo.getName = function() { alert(2); };
Foo.prototype.getName = function(){ alert(3); };
getName = function() { alert(4); };
getName(); //4
Foo().getName(); //1
getName(); //1
Foo.getName(); //2
new Foo.getName();//2 先執行Foo.getName() new關鍵字無效
(new Foo).getName();//3 先執行new Foo創建對象
new Foo().getName(); //3 先執行new Foo()創建對象
new new Foo().getName(); //3 相當于 new Foo().getName() new關鍵字無效