ES6入门详解(一) let const

在es6之前 JS实际上并没有块级作用域的概念 只有词法作用域 在es6中的let 与 const 就实现了块级作用域 和天然的模块化 var标签直接挂载到全局对象的特性无法实行模块化

let  用于for循环 let支持块级作用域 所以每次循环都是一个 单独的作用域 而重新定义循环变量 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

let命令不存在变量声明提升

let 与 const 命令会形成暂时性死区

let temp = '234'
if(true){
    console.log(temp)
    let temp = '123'
}

上面代码就是暂时性死区的运行 如果在块级作用域内 已经存在了 let const 声明的变量 那么 在这之前的范围都属于死区范围 同样 typeof 在判断未声明的变量时 会返回undefined但是在判断暂时性死区的变量就会抛出引用错误 所以在这里还是遵守规范变量先声明再使用

在定义函数时也会出现暂时性死区的概念

function fn(x = y , y = 2) {
    return x + y
}
fn()

这个时候因为y 还没有执行到 所以这时候引用Y 就会报错 如果用下面方式运行就不会报错了

function fn1(x = 2 , y = x){
    return x+y
}
console.log(fn1())

因为var的 变量声明提升机制 所以 var x = x 这是可以被执行的 结果是 undefined 但是let 并不会存在变量声明提升 let x = x 就是引用了一个不存在的变量会报错

所以暂时性死区就是说 当程序一执行到当前作用域 变量就已经存在 但是不能引用 只有在变量声明之后才可以调用 

无论是const 还是let 都不允许 在同一作用域下 重复声明 

const x = 2
const x = 2

下面来说一下块级作用域下的函数声明 这是个大坑 在es6标准中 块级作用域的funcion 声明类似于let 在块级作用域外不能被访问但实际是可以的

if(true){
    function fn(){
        console.log(111)
    }
}else{
    function fn2(){
        console.log(2222)
    }
}
console.log(fn)
console.log(fn2)

首先上述代码的执行按照标准应该报错 但实际是可以的 

好这里也就是说 在node 与 浏览器环境下 块级作用域内声明的函数 依然可以被外部 引用  并且 类似var 首先js会预处理所有的function声明 将其提升到当前词法作用域顶部 值为undefined 因为这种声明不可控性 太高而且巨坑 所以尽可能使用 函数表达式声明函数

最后说一下const const声明的是常量

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。

因为这种特性所以如果真的想彻底冻结对象需要使用 Object.freeze

const foo = Object.freeze({});

如果想要冻结对象的所有属性 可以通过递归的形式来完成

let congelation = obj => {
    Object.freeze(obj);
    //枚举对象所有的属性
    Object.keys(obj).forEach((key , i ) => {
        if(typeof obj[key] === 'object'){
            congelation(obj[key])
        }
    })
}

let obj = {
    a : {},
    b:{},
    c:2
}

congelation(obj)
obj.ss = {}

console.log(obj)

 

 

 

同一段代码为了能够在各种环境,都能取到顶层对象,现在一般是使用this变量,但是有局限性。

全局环境中,this会返回顶层对象。但是,Node 模块和 ES6 模块中,this返回的是当前模块。函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。不管是严格模式,还是普通模式,new Function('return this')(),总是会返回全局对象。但是,如果浏览器用了 CSP(Content Security Policy,内容安全政策),那么evalnew Function这些方法都可能无法使用。

如果想要在所有环境都拿到全局对象有几个方法

// 方法一
(typeof window !== 'undefined'
    ? window
    : (typeof process === 'object' &&
        typeof require === 'function' &&
        typeof global === 'object')
        ? global
        : this);

// 方法二
var getGlobal = function () {
    if (typeof self !== 'undefined') { return self; }
    if (typeof window !== 'undefined') { return window; }
    if (typeof global !== 'undefined') { return global; }
    throw new Error('unable to locate global object');
};

 

posted on 2018-04-17 11:45  素心~  阅读(179)  评论(0编辑  收藏  举报

导航