kiss keep it simple stupid
块级作用域
块作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域。
for()中也属于块级作用域,是{}的父级块作用域。
for(let i=0;i<10;i++){
let i=1;
console.log(i);//1 1 1 1 1 1 1 1 1 1
}
console.log(i);//a is not defined
暂时性死区:
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称TDZ)。
{
//TDZ开始
a=1;//
console.log(a);//ReferenceError:Cannot access 'a' before initialization
let a;//TDZ结束
console.log(a);//ReferenceError:Cannot access 'a' before initialization
a=123;
console.log(a);//123
}
var x = 1;
{
//存在暂时性死区(TDZ),当前作用域不能拿到上一层作用域中的x。在引用之前没有负值,报错。
let x = x;
console.log(x);
}
let
1、不能在同一作用域下重复声明;(Uncaught SyntaxError: Identifier 'a' has already been declared)
2、使用let var 一起也不能在同一个作用域重复声明。
3、用let定义变量时,也不能与形参同名。比如:
function test(a){
let a=0;
console.log(a);//Uncaught SyntaxError: Identifier 'a' has already been declared(未捕获的语法错误:标识符a已经声明)
}
test();
function test(a){
{
let a=0;
}
console.log(a);//undefined
}
test();
function test(a){
{
let a=0;
console.log(a);//10
}
console.log(a);//undefined
}
test();
4、let 不会变量提升,会产生一个暂时性死区。
5、let 只能在当前的块级作用域下生效。
var arr=[];
for(var i=0;i<10;i++){
arr[i]=function(){
console.log(i);
}
}
for(var i=0;i<10;i++){
arr[i]();
}
//0 1 2 3 4 5 6 7 8 9
不是因为坑多。。是因为技术不到家
var i=0;
for(;i<10;i++){
var i='a';
console.log(i);//a
}
for(let i=0;i<10;i++){
i="a";
console.log(i);//a
}
for(let i=0;i<10;i++){
var i="a";
console.log(i);//Uncaught SyntaxError: Identifier 'i' has already been declared
}
for(let i=0;i<10;i++){
let i="a";
console.log(i);//a a a a a a a a a a
}
//------------------------------------------------
var a=1;
if(1){
let a=3;
{
let a=10;
console.log(a);//10
}
console.log(a);//3
}
console.log(a);//1
//------------------------------------------------
var a=1;
if(1){
let a=3;
{
var a=10;
console.log(a);//报错
}
console.log(a);
}
console.log(a);
块级作用域等于匿名函数的立即执行?
错
for(var i=0;i<10;i++){
var i='a';
console.log(i);
}
var arr=[];
for(let i=0;i<10;i++){
arr[i]=function(){
console.log(i);
}
}
for(var k=0;k<10;k++){
arr[k]();
}
在同一个作用域下,不能声名let和function同名的变量和方法。报错
{
let a=1;
function a(){}
console.log(a);//报错 Uncaught SyntaxError: Identifier 'a' has already been declared
},
//---------------------------
{
let a=1;
{
a();
//函数提升,只在函数的作用域内提升
function a(){
console.log(22);//22
}
}
console.log(a);//1
}
const
定义常量,不可变的量
1、声明就必须要赋值;
2、不可以变更值;
3、其它性质跟let一样。
4、如果常量是引用类型,可以修改里面的值;如果想冻结该引用类型的常量不可修改,可以使用Object.freeze();
//声明就必须要赋值;
const a;
console.log(a);//Uncaught SyntaxError: Missing initializer in const declaration(const声明中缺少初始化器)
//不可以变更值
const a=1;
a=2;
console.log(a);//Uncaught TypeError: Assignment to constant variable.(未捕获类型错误:对常量变量的赋值。)
不能重复定义
const a=1;
var a=2;//Uncaught SyntaxError: Identifier 'a' has already been declared
let a=3;//Uncaught SyntaxError: Identifier 'a' has already been declared
function a(){}//Uncaught SyntaxError: Identifier 'a' has already been declared
如果常量是引用类型,可以修改里面的值
const obj={};
obj.name='mymy'
console.log(obj);//{name: "mymy"}
如果想冻结该引用类型的常量不可修改,可以使用Object.freeze();
const obj={name:'yourself'};
Object.freeze(obj);
obj.name='mymy'
console.log(obj);//{name: "yourself"}
全部的属性冰结
function myFreeze(obj) {
Object.freeze(obj);
for (var key in obj) {
if (typeof(obj[key]) === 'object' && obj[key] !== null) {
Object.freeze(obj[key]);
myFreeze(obj[key]);
}
}
}
const person = {
son: {
cai: 65,
yi: 56,
bi: {
oi: 12,
ui: 32
}
},
house: ['www', 'ccc', 'eee']
}
myFreeze(person);
person.son.bi.oi=100;
console.log(person)
全局变量
使用let、const在最顶层定义变量和常量时,不会产生全局变量。不会直接挂在window上。
其它
不建议在块级作用域当中使用函数声明的方式来声明函数,而是应该用函数表达示的方式来声明。