在javascript中, var 定义变量实际是有作用域的。
1、var变量作用域问题
1.2、假设一个变量在函数体中声明,则该变量的作用域为整个函数体则在函数体外不可以使用。
function qj() { var x = 1; x = x + 1; } x = x + 2; //Uncaught ReferenceError: x is not defined 无法在函数体外引用变量x
1.2、如果两个函数使用了相同的变量名,只要在函数内部,就不冲突
function qj() { var x = 1; x = x + 1; } function qj2() { var x = 'A'; x = x + 1; }
1.3、内部函数可以访问外部函数的成员,反之则不行
function qj() { var x = 1; // 内部函数可以访问外部函数的成员,反之则不行 function qj2() { var y = x + 1; // 2 } var z = y + 1; // Uncaught ReferenceError: y is not defined }
1.4、假设,内部函数变量和外部函数的变量重名
function qj() { var x = 1; function qj2() { var x = 'A'; console.log(' x in qj2()='+x); // x in qj()=1 } console.log('x in qj()='+x); //x in qj2()=A qj2() } qj()
结论:假设在JavaScript 中 函数查找变量从自身函数开始,由 ‘’内‘’ 向 ‘’外‘’ 查找 . 假设外部存在这个同名的函数变量,则内部函数会屏蔽外部函数的变量。
2、提升变量的作用域
JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:
'use strict'; function qj() { var x = "x" + y; console.log(x); var y = 'y'; } qj() //x undefined
问题:为什么会出现 x undefined?
说明:虽然是strict模式,但语句并不报错,var x = "x" + y;
原因是变量y
在稍后申明了。但是console.log
显示x undefined
,说明变量y
的值为undefined
。这正是因为JavaScript引擎自动提升了变量y
的声明,但不会提升变量y
的赋值。
对于上述qj()
函数,JavaScript引擎看到的代码相当于:
function qj() { var y; var x = "x" + y; console.log(x); y = 'y'; }
这个是在JavaScript建立之初就存在的特性。养成规范: 所有的变量定义都放在函数的头部,不要乱放,便于代码维护;
function qj2() { var x = 1,// x初始化为1 y = x + 1,// y初始化为2 z,i; //z和i为undefined //其他语句 }
3.全局函数
不在任何函数内定义的变量就具有全局作用域。实际上,JavaScript默认有一个全局对象window
,全局作用域的变量实际上被绑定到window
的一个属性:
x = 1; function f() { console.log(x); } f(); //1 console.log(x); //1
3.1、全局对象 window
var x = 'xxx'; alert(x); alert(window.x); // 默认所有的全局变量,都会自动绑定在 window对象下;
3.2、alert() 这个函数本身也是一个 window 变量
var x = 'xxx'; window.alert(x); var old_alert = window.alert; old_alert(x);//xxx window.alert = function () { }; window.alert(123);// 发现 alert() 失效了 //恢复 window.alert = old_alert; window.alert(456);
Javascript 实际上只有一个全局作用域, 任何变量(函数也可以视为变量),假设没有在函数作用范围内找到,就会向外查找,如果在全局作用域都没有找到,报错 RefrenceError
4、规范
由于我们所有的全局变量都会绑定到我们的 window 上。如果不同的js 文件,使用了相同的全局变量,就会造成命名冲突,并且很难被发现
如何能够减少冲突?
把自己的代码全部放入自己定义的唯一空间名字中, 降低全局命名冲突的问题~
// 唯一全局变量 var MYAPP = {}; // 定义全局变量 GodlesApp.name = 'myapp'; //其他函数 MYAPP.add = function (a,b) { return a + b; }
5、局部作用域 let
'use strict'; function aaa() { for (var i = 0; i < 100; i++) { console.log(i) } console.log(i+1); //101 }
问题: 为什么i
出了这个作用域还可以使用?
ES6
let
关键字,用let
替代var
可以申明一个块级作用域的变量
'use strict'; function aaa() { for (let i = 0; i < 100; i++) { console.log(i) } console.log(i+1); //Uncaught ReferenceError: i is not defined }
建议大家都是用 let
去定义局部作用域的变量;
6、常量 const
在ES6 之前,怎么定义常量?只有用全部大写字母命名的变量就是常量
;建议不要修改这样的值
var PI = '3.14'; console.log(PI); //3.14 PI = '213'; console.log(PI); //213 可以改变这个值
在 ES6 引入了常量关键字
const
const PI = '3.14'; // 只读变量 console.log(PI); //3.14 PI = '123'; // TypeError: Assignment to constant variable. console.log(PI); //3.14
7、解构赋值
从ES6开始,JavaScript引入了解构赋值,可以同时对一组变量进行赋值。
7.1、传统赋值
//如何把一个数组的元素分别赋值给几个变量? var array = ['hello', 'JavaScript', 'ES6']; var x = array[0]; var y = array[1]; var z = array[2];
7.2、ES6赋值
'use strict'; // 如果浏览器支持解构赋值就不会报错: var [x, y, z] = ['hello', 'JavaScript', 'ES6']; // x, y, z分别被赋值为数组对应元素: console.log('x = ' + x + ', y = ' + y + ', z = ' + z); //x = hello, y = JavaScript, z = ES6
注意:对数组元素进行解构赋值时,多个变量要用[...]
括起来。
7.2.1、如果数组本身还有嵌套,也可以通过下面的形式进行解构赋值,注意嵌套层次和位置要保持一致:
let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']]; x; // 'hello' y; // 'JavaScript' z; // 'ES6'
7.2.2、解构赋值还可以忽略某些元素:
let [, , z] = ['hello', 'JavaScript', 'ES6']; // 忽略前两个元素,只对z赋值第三个元素 z; // 'ES6'
7.2.3、如果需要从一个对象中取出若干属性,也可以使用解构赋值,便于快速获取对象的指定属性:
'use strict'; var person = { name: '小明', age: 20, gender: 'male', password: '123456', school: 'No.1 middle school' }; var {name, age, passport} = person// name, age, passport分别被赋值为对应属性 console.log('name = ' + name + ', age = ' + age + ', password = ' + password); //name = 小明, age = 20, passport = 123456
来源:https://www.cnblogs.com/godles/p/12196167.html