ES6 Let和Const命令

//let用法类似于var 但是声明的变量只在代码块中有效 注:只有在声明之后才能被使用,不同于var,不存在变量提升

{

let a =10;

var b = 11;

}

//a is not defined

//b 1



//const 声明一个只读的常量,一旦声明,常量的值就不能改变注:只有在声明之后才能被使用,不存在变量提升

const PI = 3.1415926;

//PI 3.1415926

PI = 3;

// TypeError:Assignment to constant variable

//const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心

const foo = {};

// 为 foo 添加一个属性,可以成功

foo.prop = 123;

foo.prop // 123



// 将 foo 指向另一个对象,就会报错

foo = {}; // TypeError: "foo" is read-only

//上面代码中,常量foo储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性。



const a = [];

a.push('Hello'); // 可执行

a.length = 0; // 可执行

a = ['Dave']; // 报错

//上面代码中,常量a是一个数组,这个数组本身是可写的,但是如果将另一个数组赋值给a,就会报错。

Object.freeze()

//Object.freeze() 方法可以冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。也就是说,这个对象永远是不可变的。该方法返回被冻结的对象。

var obj = {

name:'abc',

age:14,

dsc:'this is aaa'

}

var obj_2 = obj;

obj_2.age = 16;

console.log(obj); //{name: "abc", age: 16, dsc: "this is aaa"}

var obj_3 = Object.freeze(obj);

obj_3.age = 20;

obj_3.data = 'sssssssss';

console.log(obj); //{name: "abc", age: 14, dsc: "this is aaa"}

//使用了Object.freeze() 方法,不可以操作原来的obj。

// 顶层对象的属性

// 顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象。ES5 之中,顶层对象的属性与全局变量是等价的。



window.a = 1;

a // 1



a = 2;

window.a // 2

// 上面代码中,顶层对象的属性赋值与全局变量的赋值,是同一件事。

// 顶层对象的属性是到处可以读写的,这非常不利于模块化编程。另一方面,window对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。

// ES6 为了改变这一点,一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。



var a = 1;

// 如果在 Node 的 REPL 环境,可以写成 global.a

// 或者采用通用方法,写成 this.a

window.a // 1



let b = 1;

window.b // undefined

// 上面代码中,全局变量a由var命令声明,所以它是顶层对象的属性;全局变量b由let命令声明,所以它不是顶层对象的属性,返回undefined。

// JavaScript 语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。但是,顶层对象在各种实现里面是不统一的。



// 浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。

// 浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。

// Node 里面,顶层对象是global,但其他环境都不支持。

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

// 全局环境中,this会返回顶层对象。但是,Node 模块和 ES6 模块中,this返回的是当前模块。

// 函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。

// 不管是严格模式,还是普通模式,new Function('return this')(),总是会返回全局对象。但是,如果浏览器用了 CSP(Content Security Policy,内容安全策略),那么eval、new 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');

};

// 现在有一个提案,在语言标准的层面,引入globalThis作为顶层对象。也就是说,任何环境下,globalThis都是存在的,都可以从它拿到顶层对象,指向全局环境下的this。



// 垫片库global-this模拟了这个提案,可以在所有环境拿到globalThis。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值