前端宝典【犀牛书】02(变量声明+作用域)
一、变量声明
Python、Ruby、js动态语言在赋值的时候确认变量数据类型,c/c++、java是在编译时检查数据类型;
全局变量:给一个没有声明变量赋值在严格模式下会报错,非严格模式会增加一个全局变量;
局部变量:es3中调用对象的属性,es5中声明上下文对象的属性;
js没有块级作用域,即花括号的范围以外的变量在同一个作用域下都可以被访问;
变量声明会提升至函数顶部,所以请将变量声明写至函数顶部;
var
用var可以声明多个变量
eg:var i,sum;
也可以初始化赋值与声明变量写一起;
eg:var i=0,j=0
二、变量作用域
简化理解,作用域当成对象去解析变量来作为自己的属性
作用域:如果 将 一个 局部 变量 看做 是 自定义 实现 的 对象 的 属 性的 话, 那么 可以 换个 角度 来 解读 变量 作用域。 每 一段 JavaScript 代码( 全局 代码 或 函数) 都有 一个 与之 关联 的 作用域 链( scope chain)。 这个 作用域 链 是一 个 对象 列表 或者 链 表, 这 组 对象 定义 了 这段 代码“ 作用域 中” 的 变量。 当 JavaScript 需要 查找 变量 x 的 值 的 时候( 这个 过程 称做“ 变量 解析”( variable resolution)), 它 会 从 链 中的 第一个 对象 开始 查找, 如果 这个 对象 有一个 名为 x 的 属性, 则 会 直接 使用 这个 属 性的 值, 如果 第一个 对象 中 不存在 名为 x 的 属性, JavaScript 会 继续 查找 链 上 的 下一个 对象。 如果 第二个 对象 依然 没有 名为 x 的 属性, 则 会 继续 查找 下一个 对象, 以此类推。 如果 作用域 链 上 没有 任何 一个 对象 含有 属性 x, 那么 就 认为 这段 代码 的 作用域 链 上 不存在 x, 并 最终 抛出 一个 引用 错误( ReferenceError) 异常。
简化理解,函数有自己的作用域,嵌套的函数也一样,定义函数即保存作用域链,调用函数是将对象添加至保存的作用域链,并将变量储存在对象上,同时创建一个新的表示调用函数的更长作用域链,函数体内部代码相同但每次调用函数作用域链都不同。
在 JavaScript 的 最 顶层 代码 中( 也就是 不 包含 在任 何 函数 定义 内 的 代码), 作用域链 由 一个 全局 对象 组成。 在不包含嵌套的函数体内, 作用域链上有两个对象, 第一个是定义函数参数 和局部变量的对象,第二个是全局对象。 在一个嵌套 的函数体内,作用域链上至 少有 三个 对象。 理解 对象 链 的 创建 规则 是 非常 重要的。 当定义一个函数时,它实际上保存 一个 作用域 链。 当调用这个函数 时,它创建 一个 新的 对象 来 存储 它的 局部 变量, 并将这个对象 添加 至 保存 的 那个 作用域 链 上, 同时 创建 一个 新的 更长 的 表示 函数 调用 作用域 的“ 链”。 对于嵌套函数来讲,事情变得更加有趣,每次调用外部函数时,内部函数又会重新定义 一遍。 因为 每次 调用 外部 函数 的 时候, 作用域 链 都是 不同 的。 内部 函数 在 每次 定义 的 时候 都有微妙的差别—— 在每次调用 外部 函数 时, 内部 函数 的 代码 都是 相同 的, 而且 关联 这段 代码 的 作用域 链 也不 相同。
全局变量:全局范围内都起作用的变量;
局部变量:局部内起作用的变量,一般在函数体内;
eg1:
var scop="global";//全局 function cheeckscope(){ var scope="local"; //局部变量 return scope; } checkscope() =>local
eg2:
scope = "global"; // 声明 一个 全局 变量, 甚至 不用 var 来 声明
function checkscope2() {
scope = "local"; // 糟糕! 我们 刚 修改 了 全局 变量
myscope = "local"; // 这里 显 式 地 声明 了 一个 新的 全局 变量
return [scope, myscope];// 返回 两个 值
}
checkscope2() // => ["local", "local"]: 产生了 副作用
scope // => "local": 全局 变量 修改 了
myscope // => "local": 全局 命名 空间 搞乱 了
eg3:
每个函数都有它的作用域,函数可以嵌套,因此会出现作用域嵌套的情况
var scope = "global scope"; // 全局 变量
function checkscope() {
var scope = "local scope"; //局部 变量
function nested() {
var scope = "nested scope"; // 嵌套 作用域 内 的 局部 变量
return scope; // 返回 当前 作用域 内 的 值
}
return nested();
}
checkscope() // => "嵌套 作用域"