什么是作用域?
几乎所有的编程语言就是简单的在变量中存储值,并且读取和修改此值。事实上,在变量中存储值和取出值的能力,给程序赋予了状态。
如果没有这样的概念,一个程序虽然可以执行一些任务,但是它们将会受到很大的限制而且不会有趣。为了完成这个目标,制定了一些规则----作用域。
常见的作用域主要分为:全局作用域、函数作用域、块状作用域、动态作用域。
对象 | 类型 |
---|---|
global/window | 全局作用域 |
function | 函数作用域(局部作用域) |
{ } | 块状作用域 |
this | 动态作用域 |
全局作用域
变量在函数或者代码块{}外定义,即全局作用域。
在函数或者代码块{}内未定义的变量也是拥有全局作用域的(不推荐)。
var carName = " Volvo";
// 此处可调用 carName 变量
function myFunction() {
// 函数内可调用 carName 变量
}
// 用var定义的值,不管是在函数体内还是在函数体外,都被挂在window上
// 此处可调用 carName 变量
function myFunction() {
carName = "Volvo";
// 此处可调用 carName 变量
}
函数作用域
在函数内部定义的变量,就是局部作用域。
函数作用内,对外是封闭的,从外层的作用域无法直接访问函数内部的作用域!
function bar() {
var testValue = 'inner';
}
console.log(testValue); // 报错:ReferenceError: testValue is not defined
如果想读取函数内的变量,必须借助return 或者 闭包。
function bar(value) {
var testValue = 'inner';
return testValue + value;
}
console.log(bar('fun')); // "innerfun"
function bar(value) {
var testValue = 'inner';
var rusult = testValue + value;
function innser() {
return rusult;
};
return innser();
}
console.log(bar('fun')); // "innerfun"
在return 的方式中,return是函数对外交流的接口, return 可以返回的是函数,根据作用域的规则,函数内部的子函数是可以获取函数作用域内的变量的。
嵌套函数的作用域问题
// 函数作用域是向上找,不能向下找 如c:c先在test2()块中找,么有,再向上找test1()块,也没有,找全局window,也没有,则不正确
// function test1 () {
// var a = 3
// function test2 () {
// var b = 4
// // return a + b + c
// return a + b
// }
// return test2()
// }
// test1()
块状作用域
{
// 块状作用域
let a = 1
console.log(a)
}
var b = 3
let c = 4
console.log(b, c)
console.log(window.b, window.c)
//
// var定义的变量可以重复 let不允许重复定义
var b = 4
console.log(b)
// let有的特性const都有 但const只能定义常量 const要在初始化的时候进行赋值
function test3 () {
var a = 3
if (a === 3) {
var b = 4
let c = 5
// if的花括号形成不了函数作用域,无法形成壁垒---针对该问题ES6做了一个改变,只要有花括号的地方,自动形成一个块,及块状作用域 let/const
动态作用域
在 JavaScript 中很多同学对 this 的指向时而清楚时而模糊,其实结合作用域会对 this 有一个清晰的理解。
window.a = 3
function test4 () {
console.log(this.a)
// this != window
}
test4()
// 输出 3
test4.bind({ a: 100 })()
// 输出 100 此时 window.a 仍是 3
在这里 bind 已经把作用域的范围进行了修改指向了 { a: 100 },而 this 指向的是当前作用域对象