1、函数定义和调用
(1)JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数;传入的参数比定义的少也没有问题,未对应的参数值为undefined
(2)避免收到undefined
,可以对参数进行检查
(3)JavaScript还有一个免费赠送的关键字arguments
,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。也就是说,即使函数不定义任何参数,还是可以拿到参数的值。arguments
类似Array
但它不是一个Array
(4)
rest参数只能写在最后,前面用...
标识。不再需要arguments
我们就获取了全部参数
(5)如果传入的参数连正常定义的参数都没填满,也不要紧,rest参数会接收一个空数组(注意不是undefined
)
2、变量作用域
(1)变量提升。先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部。由于JavaScript的这一怪异的“特性”,我们在函数内部定义变量时,请严格遵守“在函数内部首先申明所有变量”这一规则。
(2)JavaScript默认有一个全局对象window
,全局作用域的变量实际上被绑定到window
的一个属性
(3)顶层函数的定义也被视为一个全局变量,并绑定到window
对象
(4)alert()
函数其实也是window
的一个变量
(5)不同的JavaScript文件如果使用了相同的全局变量,或者定义了相同名字的顶层函数,都会造成命名冲突,并且很难被发现。减少冲突的一个方法是把自己的所有变量和函数全部绑定到一个全局变量中
(6)变量作用域实际上是函数内部,语句块中是无法定义具有局部作用域的变量。用let
替代var
可以申明一个块级作用域的变量
(7)关键字const
来定义常量,const
与let
都具有块级作用域
3、解构赋值
(1)可以同时对一组变量进行赋值,多个变量要用[...]
括起来
(2)数组本身还有嵌套,注意嵌套层次和位置要保持一致
(3)可以忽略某些元素:let [, , z] = ['hello', 'JavaScript', 'ES6'];
(4)需要从一个对象中取出若干属性,也可以使用解构赋值,便于快速获取对象的指定属性
(5)对一个对象进行解构赋值时,同样可以直接对嵌套的对象属性进行赋值,只要保证对应的层次是一致的
(6)对对象属性进行赋值时,如果对应的属性不存在,变量将被赋值为undefined
(7)要使用的变量名和属性名不一致,可以用下面的语法获取:let {name, passport:id} = person;
(8)还可以使用默认值,这样就避免了不存在的属性返回undefined
的问题
(9)如果变量已经被声明了,再次赋值的时候,正确的写法也会报语法错误:
// 声明变量:
var x, y;
// 解构赋值:
{x, y} = { name: '小明', x: 100, y: 200};
// 语法错误: Uncaught SyntaxError: Unexpected token =
这是因为JavaScript引擎把{
开头的语句当作了块处理,于是=
不再合法。解决方法是用小括号括起来:
({x, y} = { name: '小明', x: 100, y: 200});
(10)交换两个变量x
和y
的值,可以这么写,不再需要临时变量:
var x=1, y=2;
[x, y] = [y, x];
(11)快速获取当前页面的域名和路径:
var {hostname:domain, pathname:path} = location;
(12)接收一个对象作为参数,那么,可以使用解构直接把对象的属性绑定到变量中
4、方法
(1)绑定到对象上的函数称为方法。在一个方法内部,this
始终指向当前对象
(2)函数内的this有大坑,要注意,this的指向跟运行时有关
(3)可以用函数本身的apply
方法指定this
指向的对象。第二个参数是Array
,表示函数本身的参数
(4)call()与apply()类似,但参数是按顺序传入的
(5)对普通函数调用,我们通常把this
绑定为null
(6)
利用apply()
,还可以动态改变函数的行为,如:
'use strict';
var count = 0;
var oldParseInt = parseInt; // 保存原函数
window.parseInt = function () {
count += 1;
return oldParseInt.apply(null, arguments); // 调用原函数
};