1.Js的变量特点

1.1变量声明的提升

先看一道面试题

console.log(v1);
var v1 = 100;
function foo() {
    console.log(v1);
    var v1 = 200;
    console.log(v1);
}
foo();
console.log(v1);

var声明变量时会提升到它所在作用域的顶端去执行,到我们代码所在的位置来赋值。

1.2函数的提升

函数的两种声明:

//函数声明式
function bar () {}
//函数字面量式 , 合普通变量提升的机制一样
var foo = function () {}

函数声明式的提升现象和变量提升略有不同:

console.log(bar);
function bar () {
  console.log(1);
}
//打印结果:ƒ bar () {
//  console.log(1);
//}

函数提升是整个代码块提升到它所在的作用域的最开始执行,上述代码执行顺序相当于

function bar () {
  console.log(1);
}
console.log(bar);
思考下面的代码,这就是函数优先规则。
foo(); //3
 
var foo;
 
function foo () {
    console.log(1);
}

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

下面这段代码,在低版本的浏览器中,函数提升不会被条件判断所控制,输出2;但是在高版本的浏览器中会报错,所以应该尽可能避免在块内部声明函数

foo(); //低版本:2  //高版本: Uncaught TypeError: foo is not a function
 
var a = true;
 
if(a){
    function foo () { console.log(1); }
}else{
    function foo () { console.log(2); }
}

2.ES6的块级作用域绑定

2.1 let声明

  • let声明不会被提升
  • 禁止同一作用域的重复声明
  • 块级作用域内有效

2.2 const 声明

  • 声明的值是常量,一旦被设定后不可更改和重新赋值。
  • 必须初始化。
  • 块级作用域内有效

用const声明对象

const person = {
    name: 'changchang'
}
//可以修改对象属性的值
person.name = 'zhangchangchang';

//抛出语法错误
person = {name: 'es6'}

2.3 循环中的块作用域绑定

for (let i = 0; i < 10; i++){
    process(items[i]);
}
// i在这里不可访问,抛出错误
console.log(i);

2.4 循环中的函数

var funcs = [];

for (var i = 0; i < 10; i++){
    funcs.push(function() {
        console.log(i);
    })
}

funcs.forEach((ele)=>{
    ele(); //输出10次数字10
})

//循环离的每次迭代同时共享着变量i,循环内部创建的函数全部保留了相对变量的引用。循环结束时变量i的值为10,所以forEach时每次都会输出10。
//用forEach来console.log(ele)得出ƒ (){console.log(i)},而此时i=10,所以输出10次10

循环中的立即执行函数(IIFE)

var funcs = [];

for (var i = 0; i < 10; i++){
    funcs.push((function(value) {
        return function(){
            console.log(value);
        }
    }(i))); //把当前的i存放到形参value里
}

funcs.forEach((ele)=>{
    ele(); //输出0 1 2...
})

//如果console.log(ele),得出ƒ (){console.log(value);}

循环中的let声明

var funcs = [];

for (let i = 0; i < 10; i++){
    funcs.push(function() {
        console.log(i);
    })
}

funcs.forEach((ele)=>{
    ele(); //输出0 1 2 ...
})

//let在每次迭代循环都会创建一个新变量

对于for-in合for-of也是一样的

var funcs = [];
var object = {a: true, b:true, c: true};

for (let key in object){
    funcs.push(function(){
        console.log(key);
    });
}

funcs.forEach((ele)=>{
    ele(); //输出a b c ...
})

循环中的const声明

// 报错
for (const i = 0; i < 10; i++){
    ...
}

var object = {a: true, b:true, c: true};
// 可以正常输出,因为每次迭代都会创建一个新绑定
for (const key in object){
    console.log(key);
}

参考文章:
《深入理解ES6》
https://blog.csdn.net/qq_3971...


张长长
67 声望4 粉丝