函数中的this
function定义的函数中的this,是可以变化的,遵循的规则是: 谁调用就指向谁, 如果没有明确的调用者,则指向window
- 会变化的this
function demo() {
console.log(this);
}
// 自己执行
demo(); // window
document.onclick = demo; // document
var obj = {
demo
}
obj.demo(); // obj
setInterval(demo, 1000); // window
setTimeout(demo, 1000); // window
改变函数中this指向的方法
这三个都是函数的方法
- call
call可以调用函数 它的作用是执行函数并改变函数中的this指向 如果原函数需要参数 需要往call的参数列表中传递 第一个参数是this 往后的每一个参数是原函数所需参数
function sum(a, b) {
console.log(this);
console.log(a, b);
}
sum.call(); // 不传递参数时 this指向window a和b 都是undefined
sum.call(document);// this指向了document a 和 b都是undefined
sum.call(document.body, 1);// this指向body a时1 b是undefined
sum.call(document.body, 1, 3);// this指向body a时1 b是3
- apply
apply可以调用函数 它的作用是执行函数并改变函数中的this指向 如果原函数需要参数 需要往apply的参数列表中传递 第一个参数是this 第二个参数是数组 数组中的每一个成员是原函数所需的参数 按照数组顺序一一对应
function sum(a, b) {
console.log(this);
console.log(a, b);
}
sum.apply(); // 不传递参数时 this指向window a和b 都是undefined
sum.apply(document); // this指向了document a 和 b都是undefined
sum.apply(document, [1]); // this指向了document a 是 1 b 是undefined
sum.apply(document, [1, 3]); // this指向了document a 是 1 b 是 3
- bind
bind 是ES5中新增的方法 作用是在定义的时候改变this指向(其实是返回了一个新的函数)
function sum(a, b) {
console.log(this);
console.log(arguments);
}
// 调用bind方法
var fun = sum.bind(document, 1, 2, 0.4, 0.5, 0.6);
// fun是一个函数
fun(3, 4, 5, 6, 7);
console.log(sum === fun); // false
箭头函数
ES6中新增的一种函数定义方式
箭头函数 var name = () => {}
- demo
var fun = () => {
console.log("hello 我是一个箭头函数");
}
fun(); // hello 我是一个箭头函数
console.log(typeof fun); // function
- 箭头函数中的this
箭头函数中的this 只有在定义箭头函数时能够确定 而且一旦确定再也不会更改
let fun = () => {
console.log(this);
}
fun(); // window
document.onclick = fun; // 依然是window
let obj = {
fun
}
obj.fun(); // window
fun.call(document.body); // window
fun.apply(document.documentElement); // window
var fun1 = fun.bind(document);
fun1(); // window
总结:经过各种测试 我们发现无论如何 箭头函数中的this是不会发生变化的
- 函数的参数默认值
function fun(a = [], b = {}) {
console.log(a, b);
}
fun(); // 不传递参数 但是因为在定义形参时 通过赋值语法进行了默认值的赋值 所以依然可
fun(0); // 一旦传递了参数 不论传递的是什么 传递了值的参数 将不会再使用默认值
fun("a0", "b1");
箭头函数中依旧如上写法
- 函数中没有arguments
let fun = () => {
console.log(arguments);
}
fun(); // 报错
- 箭头函数的简写形式
- 如果参数只有一个 那么可以省略圆括号
- 如果函数体中只有一条代码并且还是返回值 则可以省略大括号 和return
var fun = x => x * x * x * x;
var result = fun(5);
console.log(result); // 625
拓展语法(…)
- 作用1 作为函数的参数收集器
// ...语法作用之一: 获取参数为数组
let fun = (...a) => {
console.log(a);
}
fun();
fun(1);
fun(1, 2);
fun(1, 2, 3);
- 作用2 解构时使用
var arr = "abcdefg".split("");
console.log(arr); // ["a","b","c","d","e","f","g"]
var [a,b,c, ...d] = arr;
console.log(a, b, c); // a b c
console.log(d); // ["d","e","f","g"]
- 作用3 传递参数时使用
var arr = "abcdefg".split("");
var [a,b,c, ...d] = arr;
console.log(arr);
console.log(d);
// 将arr数组中最后一项 “g”去掉 并将d数组中 ["d", "e", "f",
arr.splice(arr.length - 1, 1, ...d);
console.log(arr); // ["a","b","c","d","e","f","d","e","f","g"]
额外补充
- bind方法的实现
// 定义一个函数
function sum(a, b) {
console.log(this);
console.log(arguments);
}
// 模拟bind方法
function bind(sum, target) {
var arr = [].slice.call(arguments, 2);
return function() {
var arr1 = [].slice.call(arguments);
sum.apply(target, arr.concat(arr1));
}
}
var fun = bind(sum, document.body, 1, 26, 7, 8, 9);
fun(10, 11, 12, 13); // this指向document.body 参数为 [1, 26, 7, 8, 9, 10, 11, 12, 13]