在函数体内,局部变量优先级高于全局变量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 var scope = 'global' ;function checkscope () { var scope = 'local' ; return scope; } checkscope(); var scope = 'global' ;function checkScope () { var scope = 'local' ; function nested () { var scope = 'nested scope' ; return scope; } return nested(); } checkScope();
声明提前
JavaScript的函数作用域是指函数内声明的所有变量在函数体内始终是可见的。有意思的是,这意味着变量在声明之前甚至已经可用。JavaScript的这个特性被非正式的称为声明提前(hoisting)
,即JavaScript函数里声明的所有变量都被提前至函数体的顶部。
1 2 3 4 5 6 var scope = 'global' ;function f ( ) { console .log (scope); var scope = 'local' ; console .log (scope); }
上面例子里的f函数,第一行的console.log(scope)
没有输出’global’是因为函数作用域的特性,局部变量在整个函数体始终是有定义的,也就是说,在函数体内的局部变量覆盖了同名的全局变量。 没有输出’local’是因为只有在函数执行到var语句的时候,局部变量才会被真正赋值。 上面的例子等价于:
1 2 3 4 5 6 function f ( ) { var scope; console .log (scope); scope = 'local' ; console .log (scope); }
运算符
当运算符在操作数之前,称为‘前增量’运算符,它对操作数进行增量运算,并返回计算后的值; 当运算符在操作数之后,称为‘后增量’运算符,它对操作数进行增量计算,但返回未做增量计算的值。
1 2 var i = 1 ;j = ++i; //i和j值都是2 var i = 1 ;j = i++; // i是2 ,j是1
throw语句
throw语句用来抛出一个用户自定义的异常。当前函数的执行将被停止(throw之后的语句将不会执行),并且控制将被传递到调用堆栈中的第一个catch块。如果调用者函数中没有catch块,程序将会终止。
1 2 3 4 5 6 7 8 9 function add (num) { if (num < 0 ) { throw new Error ('num不能是负数'); } for (let i = 0 ; i < num; i++) { console.log (i); } }add (-1 );
当抛出异常时,JavaScript解释器会立即停止当前正在执行的逻辑,并跳转至就近的异常处理程序。
try/catch/finally语句 1 2 3 4 5 6 7 8 9 try { }catch (e) { }finally { }
1 2 3 4 5 6 7 8 9 10 11 12 13 try { let num = new Number (prompt ('请输入一个正整数' )); if (num < 0 ) { throw new Error ('num不是正整数' ); } console .log (num * num); }catch (e){ console .log (e); }finally { console .log ('执行结束' ); }
with语句
JavaScript查找某个未使用命名空间的变量时,会通过作用域链来查找,作用域链是跟执行代码的context或者包含这个变量的函数有关。’with’语句將某个对象添加的作用域链的顶部,如果在statement中有某个未使用命名空间的变量,跟作用域链中的某个属性同名,则这个变量将指向这个属性值。如果沒有同名的属性,则将拋出ReferenceError异常。
1 2 3 4 5 6 7 with (document .forms[0 ] ){ name.value = '' ; age.value = '' ; sex.value = '' ; }
创建对象
可以通过对象直接量、关键字new和es6中的Object.create()函数来创建对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 let obj = {};let arr = [];let obj = new Object ();let arr = new Array ();let date = new Date ();let reg = new RegExp ('js' ); const person = { isHuman : false , printIntroduction : function ( ) { console .log (`My name is ${this .name} . Am I human? ${this .isHuman} ` ); } };const me = Object .create (person); me.name = "Matthew" ; me.isHuman = true ; me.printIntroduction ();
属性getter和setter
在es6中,属性值可以用一个或者两个方法替代,这两个方法就是getter和setter。由getter和setter定义的属性称做’存取器属性’(accessor property),它不同于’数据属性’(data property),数据属性只有一个简单的值。
下面是一个get的demo:
1 2 3 4 5 6 7 8 let obj = { x: 4 , y: 2 , get z () { return this .x * this .y; } } console.log(obj.z);
当程序查询存取器的属性值时,JavaScript代用getter方法(无参数),这个方法的返回值就是该属性存取表达式的值。当程序设置一个存取器属性值时,JavaScript调用setter方法,将赋值表达式右侧的值当作参数传入setter。从某种意义上来说,这个方法负责设置属性值,可以忽略该方法的返回值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <button id ="btn" > click it</button > <script type ="text/javascript" > let obj = { $n :0 , get next (){return this .$n ++}, set next (n ){ if (n>=this .$n ){ this .$n = n; } else { throw "序列号的值不能比当前值小" ; } } }; document .getElementById ('btn' ).onclick = function increase ( ) { console .log (obj.next ); obj.next = 10 ; } </script >
稀疏数组
稀疏数组就是包含从0开始的不连续索引的数组。通常,数组的length属性值代表数组中元素的个数。如果数组是稀疏的,length属性值大于元素的个数。
清空数组的小技巧 设置length属性为一个小于当前长度的非负整数n时,当前数组中那些索引值大于或等于n的元素将从中删除
1 2 3 4 let arr = [1 ,2 ,3 ,4 ,5 ];console .log (arr); arr.length = 0 ;console .log (arr);
还可以将数组的length属性值设置为大于其当前的长度。实际上并不会向数组中添加新的元素,它只是在数组尾部创建了一个空的区域。
1 2 3 4 let arr = [1 ,2 ,3 ,4 ,5 ];console .log (arr); arr.length = 7 ;console .log (arr);