什么是javaScript的作用域
先浅认识一下在javaScript中的编译与执行
1.编译
所谓编译就是找到某个域当中的有效标识符; 而函数在执行的时候才会产生作用域
2.执行
变量的查找会从内到外的作用域中查找,不能从外到内。
什么是作用域
JavaScript作为一门非常流行的编程语言,其作用域是其最重要的特性之一。它可以使代码在不同的区域中被访问和利用,同时也可以防止变量值的污染和混乱。在JavaScript中作用域是在运行时代码中的某些特定部分中变量,函数和对象的可访问性,也就是就是变量和函数的可访问范围。
作用域: js是弱类型的动态语言,不声明变量类型。某一个变量被定义类型,该变量可以根据环境变化自动进行转换,不需要经过显性强制转化。
1.全局作用域
直接编写在 script 标签之中的JS代码,都是全局作用域; 或者是一个单独的 JS 文件中的。 全局作用域在页面打开时创建,页面关闭时销毁。
var a = 1
function foo() {
console.log(a)
}
foo()
以上代码只定义a一个变量,其可作用于全局。执行结果:1
2.局部(函数)作用域
在函数内部就是局部作用域,这个代码的名字只在函数的内部起作用; 调用函数时创建函数作用域,函数执行完毕之后,函数作用域销毁; 每调用一次函数就会创建一个新的函数作用域,它们之间是相互独立的。
var a = 1
function foo() {
var a = 2
console.log(a)
}
foo()
以上代码定义了两个a的变量,执行结果:2,这就是上面提到的在代码的执行中变量的查找会从内到外的作用域中查找。
var a = 1
function foo() {
var a = 2
}
console.log(a)
foo()
以上代码同样定义了两个a的变量,执行结果却为:a is not defiend。这便是在代码的执行中变量的查找不能从外到内的作用域中查找。
3.块级作用域
1.补充说明:声明提升
1).var 声明的变量存在声明提升,提升到当前作用域的顶端。例如:我们打出
console.log(a)
var a = 2
而编译器会认为
var a
console.log(a)
a = 2
此时执行结果为:undefined
2).函数声明会整体提升。
foo()
function foo() {
console.log(123)
}
此时执行函数在函数体前面依旧可以成功执行出结果:123
2.let和const
1.let 或 const + {} 形成块级作用域。
if(1) {
var a = 1
}
console.log(a);
执行结果:1
if(1) {
let a = 1 //let换成 const同理
}
console.log(a);
无法执行,编译器报错。
2.let和const的共同点
(1).二者都不能声明提升
console.log(a);
let a = 1; //let换成const 同理
编译器报错
(2).二者都不能重复声明同一变量
let a = 1;
let a = 2; //let换成const 同理
console.log(a);
编译器报错
3.let和const的区别
const声明的变量值不能被修改。
const a = 1
a = 'hello'
console.log(a)
编译器报错
4.欺骗词法作用域
1.eval
让不属于这里的代码变成就是写在这里的
function foo(str){
eval(str) //var b = 2
var a= 1
console.log(a,b);
}
foo('var b = 2');
执行结果:1,2
2.with
(1).可以批量化修改对象的属性
//当我们要将obj中元素都加1
var obj = {
a:1,
b:2,
c:3
}
obj.a = 2
obj.b = 3
obj.c = 4
//但我们可以使用with简化操作
var obj = {
a:1,
b:2,
c:3
}
with(obj){
a = 2,
b = 3,
c = 4
}
(2).当修改对象中不存在的属性时,该属性会泄露到全局成为全局变量。
function foo (obj){
with(obj){
a = 2
}
}
var o1 = {
a:3
}
var o2 = {
b:4
}
foo(o2)
console.log(a)
所以执行结果为:2