变量与作用域
1664 字
8 分钟
变量与作用域
变量
- 字面量
字面量(常量),都是一些不可改变的值
比如 :1 2 3 4 5
字面量都是可以直接使用,但是我们一般都不会直接使用字面量 - 变量
变量可以用来保存字面量,而且变量的值是可以任意改变的
变量更加方便我们使用,所以在开发中都是通过变量去保存一个字面量,而很少直接使用字面量,可以通过变量对字面量进行描述
传递参数
- 所有函数的参数都是按值传递的,在按值传递参数时,值会被复制到一个局部变量中(也就是arguments对象中的一个槽位) function setName(obj) { obj.name = “aaa” obj = new Object() obj.name = “bbb” } var person = new Object() setName(person) console.log(person.name) // aaa 如果是按照引用传递的话,person将会指向name为”bbb”的对象,而不是任然指向”aaa”的对象。 当obj在函数内部重写时,它变成了一个指向本地对象的指针,而那个本地对象在函数执行结束时就被销毁了。
执行上下文与作用域
变量提升与函数提升
-
变量声明提升:通过var定义(声明)的变量, 在定义语句之前就可以访问到,但值: undefined
-
函数声明提升:通过function声明的函数, 在之前就可以直接调用,但 值: 函数定义(对象)
//变量提升console.log(a1) //可以访问, 但值是undefinedvar a1 = 3//函数提升a2() // 可以直接调用,输出 a2()function a2() {console.log('a2()')}a3() //报错var a3 = function(){console.log('a3')}
遇到函数表达式 var a3 = function(){}时,首先会将var a3上升到函数体顶部,然而此时的 a3 的值为 undefined,所以执行a3()报错。
- 注:
-
当遇到函数和变量同名且都会被提升的情况,函数声明优先级比较高(实际上是变量先提升到全局作用域中,但值为undefined,然后函数提升并且给函数直接赋值),因此变量声明会被函数声明所覆盖,但是可以重新赋值。
console.log(a) //输出:function a(){ console.log('函数') }function a() {console.log("函数")} //var a = "变量"console.log(a) //输出:'变量'
-
function 声明的优先级比 var 声明高,也就意味着当两个同名变量同时被 function 和 var 声明时,function 声明会覆盖 var 声明。
这代码等效于:
function a() { console.log("函数"); } var a console.log(a) //输出:function a(){ console.log('函数') } a = "变量" //赋值 console.log(a) //输出:'变量'执行上下文
全局执行上下文
* 在执行全局代码前将window确定为全局执行上下文* 对全局数据进行预处理 * var定义的全局变量==>undefined, 添加为window的属性 * function声明的全局函数==>赋值(fun), 添加为window的方法 * this==>赋值(window)* 开始执行全局代码函数执行上下文
* 在调用函数, 准备执行函数体之前, 创建对应的函数执行上下文对象* 对局部数据进行预处理 * 形参变量==>赋值(实参)==>添加为执行上下文的属性 * arguments==>赋值(实参列表), 添加为执行上下文的属性 * var定义的局部变量==>undefined, 添加为执行上下文的属性 * function声明的函数 ==>赋值(fun), 添加为执行上下文的方法 * this==>赋值(调用函数的对象)* 开始执行函数体代码执行上下文栈
JavaScript 引擎创建了执行上下文栈来管理执行上下文。可以把执行上下文栈认为是一个存储函数调用的栈结构,遵循后进先出的原则。
- JavaScript 执行在单线程上,所有的代码都是排队执行,遵循后进先出的原则。
- 一开始浏览器执行全局的代码时,首先创建全局的执行上下文,压入执行栈的顶部。
- 每当进入一个函数的执行就会创建函数的执行上下文,并且把它压入执行栈的顶部。当前函数执行完成后,当前函数的执行上下文出栈,并等待垃圾回收。
- 浏览器的 JS 执行引擎总是访问栈顶的执行上下文。
- 全局上下文只有唯一的一个,它在浏览器关闭时出栈。
-
var color = "blue"function changeColor() {var anotherColor = "red"function swapColors() {var tempColor = anotherColoranotherColor = colorcolor = tempColor}swapColors()}changeColor()
- 当上述代码在浏览器中加载时,JavaScript 引擎会创建一个全局执行上下文并且将它推入当前的执行栈
- 调用 changeColor 函数时,此时 changeColor 函数内部代码还未执行,js 执行引擎立即创建一个 changeColor 的执行上下文,然后把这执行上下文压入到执行栈中。
- 执行 changeColor 函数过程中,调用 swapColors 函数,同样地,swapColors 函数执行之前也创建了一个 swapColors 的执行上下文,并压入到执行栈中。
- swapColors 函数执行完成,swapColors 函数的执行上下文出栈,并且被销毁。
- changeColor 函数执行完成,changeColor 函数的执行上下文出栈,并且被销毁。
作用域
- 我们可以这样理解:作用域就是一个独立的地盘,让变量不会外泄、暴露出去。也就是说作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。
- 在创建函数会创建函数作用域,函数作用域的含义是指,属于这个函数的全部变量都可以在整个函数的范围内使用及复用(事实上在嵌套的作用域中也可以使用)。而外部作用域无法使用内部作用域的变量
- 在ES6中引入了let关键字,用来在任意块中声明变量,在块中的变量无法在块作用域在进行引用 var foo = true; if (foo) { { // <— 显式的快 let bar = foo * 2; bar = something( bar ); console.log( bar ); } } console.log( bar ); // ReferenceError
作用域链
-
作用域链是由多个上下级关系的作用域形成的链,他的方向是从下向上的(从内向外),查找变量时就是沿着作用域链来查找的 var a = 2; function fn1() { var b = 3; function fn2() { var c = 4; console.log(c); console.log(b); console.log(a); console.log(d); }
fn2();}fn1(); //4, 3, 2, ReferenceError上面例子中的作用域链就是fn2函数作用域—>fn1函数作用域—>全局作用域
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
相关文章智能推荐
1
线程机制与事件机制
javaScript进程:程序的一次执行, 它占有一片独有的内存空间 线程: CPU的基本调度单位, 是程序执行的一个完整流程
2
对象
javaScript对象是JS中的引用数据类型 对象是一种复合数据类型,在对象中可以保存多个不同数据类型的属性 使用 typeof 检查一个对象时,会返回 object
3
函数
javaScript函数也是一个对象,也具有普通对象的功能 函数中可以封装一些代码,在需要的时候可以去调用函数来执行这些代码 使用typeof检查一个函数时会返回function
4
字符串方法
javaScript在底层字符串是以字符数组的形式保存的 var str = "abc";// ["a","b","c"] length属性 可以用来获取字符串的长度 console.log(str.length); //输出字符串str的长度
5
正则表达式
javaScript正则表达式用于定义一些字符串的规则,计算机可以根据正则表达式,来检查一个字符串是否符合规则,获取将字符串中符合规则的内容提取出来
随机文章随机推荐














