arguments(关键字)
JavaScript函数允许接收任意个参数,于是我们就不得不用arguments来获取所有参数
1 · 只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数
2 · 类似Array但它不是一个Array
function foo(x) {
console.log('x = ' + x); // 10
for (var i=0; i<arguments.length; i++) {
console.log('arg ' + i + ' = ' + arguments[i]); // 10, 20, 30
}
}
foo(10, 20, 30);
3 · 即使函数不定义任何参数,还是可以拿到参数的值
function abs() {
if (arguments.length === 0) {
return 0;
}
var x = arguments[0];
return x >= 0 ? x : -x;
}
abs(); // 0
abs(10); // 10
abs(-9); // 9
4 · 最常用于判断传入参数的个数
// foo(a[, b], c)
// 接收2~3个参数,b是可选参数,如果只传2个参数,b默认为null:
function foo(a, b, c) {
if (arguments.length === 2) {
// 实际拿到的参数是a和b,c为undefined
c = b; // 把b赋给c
b = null; // b变为默认值
}
// ...
}
//要把中间的参数b变为“可选”参数,就只能通过arguments判断,然后重新调整参数并赋值。
rest参数(ES6)
//为了获取除了已定义参数a、b之外的参数,我们不得不用arguments,并且循环要从索引2开始以便排除前两个参数
function foo(a, b) {
var i, rest = [];
if (arguments.length > 2) {
for (i = 2; i<arguments.length; i++) {
rest.push(arguments[i]);
}
}
console.log('a = ' + a);
console.log('b = ' + b);
console.log(rest);
}
使用rest参数,上面的函数可以改写为:
function foo(a, b, ...rest) {//...ES6新增运算符
console.log('a = ' + a);
console.log('b = ' + b);
console.log(rest);
}
foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]
foo(1);
// 结果:
// a = 1
// b = undefined
// Array []
· 传入的参数先绑定a、b,多余的参数以数组形式交给变量rest,所以,不再需要arguments我们就获取了全部参数。
· 如果传入的参数连正常定义的参数都没填满,也不要紧,rest参数会接收一个空数组(注意不是undefined)*
解构赋值(ES6)
//对数组元素进行解构赋值时,多个变量要用[...]括起来
var [x, y, z] = ['hello', 'JavaScript', 'ES6'];
//如果数组本身还有嵌套,注意嵌套层次和位置要保持一致
let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']];
x; // 'hello'
y; // 'JavaScript'
z; // 'ES6'
//解构赋值还可以忽略某些元素
let [, , z] = ['hello', 'JavaScript', 'ES6']; // 忽略前两个元素,只对z赋值第三个元素
z; // 'ES6'
//从一个对象中取出若干属性,也可以使用解构赋值,便于快速获取对象的指定属性
var person = {
name: '小明',
age: 20,
gender: 'male',
passport: 'G-12345678',
school: 'No.4 middle school'
};
var {name, age, passport} = person;
//对一个对象进行解构赋值时,同样可以直接对嵌套的对象属性进行赋值,只要保证对应的层次是一致的
var person = {
name: '小明',
age: 20,
gender: 'male',
passport: 'G-12345678',
school: 'No.4 middle school',
address: {
city: 'Beijing',
street: 'No.1 Road',
zipcode: '100001'
}
};
var {name, address: {city, zip}} = person;
name; // '小明'
city; // 'Beijing'
zip; // undefined, 因为属性名是zipcode而不是zip,获取方法如下一个例子
// 注意: address不是变量,而是为了让city和zip获得嵌套的address对象的属性:
address; // Uncaught ReferenceError: address is not defined
//如果要使用的变量名和属性名不一致,可以用下面的语法获取:
var person = {
name: '小明',
age: 20,
gender: 'male',
passport: 'G-12345678',
school: 'No.4 middle school'
};
// 把passport属性赋值给变量id:
let {name, passport:id} = person;
name; // '小明'
id; // 'G-12345678'
// 注意: passport不是变量,而是为了让变量id获得passport属性:
passport; // Uncaught ReferenceError: passport is not defined
//解构赋值还可以使用默认值,这样就避免了不存在的属性返回undefined的问题
var person = {
name: '小明',
age: 20,
gender: 'male',
passport: 'G-12345678'
};
// 如果person对象没有single属性,默认赋值为true:
var {name, single=true} = person;
name; // '小明'
single; // true
有些时候,如果变量已经被声明了,再次赋值的时候,正确的写法也会报语法错误
// 声明变量:
var x, y;
// 解构赋值:
{x, y} = { name: '小明', x: 100, y: 200};
// 语法错误: Uncaught SyntaxError: Unexpected token =
//正确写法
({x, y} = { name: '小明', x: 100, y: 200});
this
1、第一个坑
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};
xiaoming.age(); // 25, 正常结果
getAge(); // NaN
//以对象的方法形式调用,比如xiaoming.age(),该函数的this指向被调用的对象
//单独调用函数,比如getAge(),此时,该函数的this指向全局对象,也就是window
//巨坑
var fn = xiaoming.age; // 先拿到xiaoming的age函数
fn(); // NaN
//要保证this指向正确,必须用obj.xxx()的形式调用
①、解决方法1:apply(arg1,arry)(函数本身的方法)
它接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};
xiaoming.age(); // 25
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空
②、解决方法2:call()
类似call(),区别在于:
· apply()把参数打包成Array再传入;
· call()把参数按顺序传入。
getAge.apply(xiaoming, [arg1,arg2]); // 25, this指向xiaoming, 参数为[arg1,arg2]
getAge.call(xiaoming, arg1,arg2); // 25, this指向xiaoming, 参数为arg1,arg2
2、第二个坑
var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
function getAgeFromBirth() {
var y = new Date().getFullYear();
return y - this.birth;
}
return getAgeFromBirth();
}
};
xiaoming.age(); // Uncaught TypeError: Cannot read property 'birth' of undefined
//原因是this指针只在age方法的函数内指向xiaoming,在函数内部定义的函数,this又指向undefined了!(在非strict模式下,它重新指向全局对象window!)
①、解决方法:用一个that变量首先捕获this
var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
var that = this; // 在方法内部一开始就捕获this
function getAgeFromBirth() {
var y = new Date().getFullYear();
return y - that.birth; // 用that而不是this
}
return getAgeFromBirth();
}
};
xiaoming.age(); // 25
网友评论