版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013862108/article/details/83216781
let 声明的变量只能在它所在的代码中有效
{
let a=10;
var b=1;
}
console.log(a);
console.log(b);
for循环 中let变量
var a=[];
for(let i=0; i< 10; i++){
//每一次循环的变量i其实都是一个新的变量
//for循环的一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
a[i] = function () {
console.log(i);
};
}
a[6]();
a[5]();
// console.dir(a[5]);
// console.dir(a[6]);
函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域
for(let i=0; i< 3;i++){
let i = 'abc';
console.log(i);
}
//上面的例子证明了: 函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。
//let 声明的变量不存在"变量提升"! console.log(foo); var foo = 2; //let的情况 //console.log(bar); //报错 bar is not defined let bar = 2;
暂时性死区TDZ temporal dead zone
好习惯:在使用变量之前一定要先声明!
//暂时性死区TDZ temporal dead zone TDZ
var tmp = 123;
if(true){
//TDZ开始
//tmp = 'abc'; //ReferenceError 报错
//TDZ结束
let tmp;
}
//ES6规定,如果区块中存在let 和const命令,这个区块对这些命令声明的变量,一开始就形成了封闭作用域,凡是在声明之前就使用这些变量,就会报错。
//"暂时性死区"也意味着typeof不再是一个百分之百安全的操作
typeof x;
let x;
//在没有let 之前,typeof运算符是百分之百安全的,现在不成立了。
//所以呢, 好的习惯是:在使用变量前一定要先声明!!!
function bar(x=2, y=x) {
//function bar(x=y, y=2) { //报错了y未定义
return [x,y];
}
bar();
//ES6 规定暂时性死区; let, const语句不出现变量提升
不允许重复声明
//不允许重复声明; 不允许重复声明
function func() {
let a = 10;
var a = 1;
}
func();
function func() {
let a = 10;
let a = 1;
}
func(); //调用就报错
//不能在函数内部重新声明参数
function func(arg) {
let arg; //报错
}
function func(arg) {
{
let arg; //不报错
}
}
块级作用域
ES5 只有全局作用域和函数作用域,没有块级作用域,会出现场景
一: 内层变量可能覆盖外层变量
//一: 内层变量可能覆盖外层变量
var tmp = new Date();
function f(){
console.log(tmp);
//if(false){
if(true){
console.log('b:',b);
//var tmp = 'hello world';
let tmp = 'hello world';
var b=3;
}
console.log(tmp);
console.log('b:',b);
}
f();
//用来计数的循环变量泄露为全局变量。
var s = 'hello';
for(var i =0; i< s.length; i++){
console.log(s[i]);
}
console.log(i);
ES6块级作用域
function f1() { //let n = 5; var n = 5; if(true){ let n = 10; //var n = 10; } console.log(n); //5 } f1();
ES6允许作用域任意嵌套 外层作用域无法读取内层作用域的变量 内层作用域可以定义外层作用域的同名变量 {{{{ let insane = 'Hello world'; {let insane = 'Hello'} }}}}
块级作用域的出现,使得广泛应用的立即执行函数表达式不再必要 (function () { var tmp = "..."; })(); //块级作用域写法 { let tmp = "..." }
ES6中规定块级作用域中,可以声明函数,函数的行为类似于let ,在块级作用域外不可引用 实际上ES6浏览器中://node 中也是这样 --允许在块级作用域内声明函数 ---函数声明类似于var ,即会提升到全局作用域或函数作用域的头部 ---同时,函数声明还会提升到所在的块级作用域的头部
//所以以下会报错
function f() {
console.log('I am outside!');
}
(function () {
console.log(f);
console.log(typeof f);
console.dir(f);
//if(false){
if(true){
//重复声明一次函数f
// function f() { //注释掉看看
// console.log('I am inside!')
// }
}
f();
}());
考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数,如果确实需要,应该写成函数表达式。!
//小细节,如果想在块级作用下声明函数,必须有大括号;不重要的知识点
const
声明一个只读的常量,一旦声明,常量的值就不能改变
const 一旦声明,就必须马上初始化
const foo=123;
if(true){ const MAX = 5; } //console.log(MAX) // 报错 MAX is not defined 注意, const声明的常量也是不提升,同样存在暂时性死驱,只能在声明的位置后面使用。 const 声明的常量,也与let 一样不可重复声明 var message = "Hello!"; let age = 25; //以下两行都会报错 //const message = "Goodbye!"; //const age = 30;
const 本质 只能保证 指向的地址是固定的, ;简单的类型数据(数值,字符串,布尔值)就保存在变量指向的那个内存地址,因此等于常量; const foo = {}; foo.prop = 123; foo.prop //将foo指向另一个对象就会报错 //foo = {} const a = []; a.push('hello'); //可执行 a.length = 0; //可执行 //a = ['Dave']; //报错
确实想把对象冻结,怎么做?
const foo = Object.freeze({name: 'zhaosi', age : 29, order :{}}); foo.prop = 123; //不起作用; 严格模式下,该行会报错。 console.log(foo); foo.age = 40; //不可修改; 不起作用,也不报错 console.log(foo); foo.order.num = 3; //还是能修改的,还是不彻底的呀! console.log(foo); //{ name: 'zhaosi', age: 29, order: { num: 3 } }
彻底冻结该怎么做?
//写一个冻结函数
var constantize = (obj) =>{
Object.freeze(obj);
Object.keys(obj).forEach((key, i) => {
if(typeof obj[key] === 'object'){
console.log('free');
constantize(obj[key]);
}
})
}
var dongjie = {name : 'liang', age : 28, info :{num : 3}}
dongjie.info.num =5;
constantize(dongjie);
//Object.freeze(dongjie);
dongjie.info.num = 8; //怎么没冻住 info呢?
dongjie.age = 22;
console.log(dongjie);
ES6声明变量的六种方式 //var function let const import class 顶层对象的属性 在浏览器环境中指的是 window 对象; Node 指的是 global 对象; ES5 中 顶层对象 ==== 全局变量 ES6中 var function 声明的的全局变量, 依旧是顶层对象的属性; let , const , class 声明的全部变量不属于顶层对象的属性。 // var a = 1; //console.log(global.a); //undefined node 中 console.log(window.a); //1 浏览器 let b = 1; //console.log(global.b); //undefined node中 console.log(window.b); //undefined 浏览器
// //global 对象
var getGlobal = function () {
if(typeof self !== 'undefined'){
return self;
}
if(typeof window !== 'undefined'){
return window;
}
if(typeof global !== 'undefined'){
return global;
}
}
console.log(getGlobal());