一、箭头函数
var n = 100;
let obj = {
id:'11',
name:'邱顺俊',
n:0,
say(){
setTimeout(()=>{
this.n++;
console.log(this.n);
}, 1000);
}
};
obj.say(); //==>1
箭头函数没有自己的this,所用到的是当前所处上下文中的this
在Function.prototype上的三个方法:call/apply/bind 都是用来改变this指向的
二、 CALL/APPLY的用法
func.call(context, arg1, arg2, …)
func.apply(context, [argsArray])
CALL/APPLY
① 立即执行函数
② 改变函数中的this为:context参数
③ 给函数传递参数信息:
=> CALL 接收的是参数列表
=> APPLY 接收的是数组
这里,以call为例
function fn(x,y){
console.log(this, x+y);
}
let obj = {
id:'11',
name:'邱顺俊',
};
fn.call(obj, 10, 20);
输出的结果是:
fn.call(obj, 10, 20)
①这句代码的意思是:
fn实例基于__proto_ 找到Function.prototype原型上的call方法,然后把call方法执行
=> call方法中的this:fn (因为fn.call,call的this是fn)
=> context存储的是参数:obj
② call方法内部功能是:
=> 把fn函数立即执行,即:call方法中的this执行
=> 把fn中的this改变为第一个参数context:obj
=> 其余的参数依次传递给fn
即:把fn执行,并让fn中的this变为obj,并且把除了obj外的剩余参数,依次传递给fn
三、重写内置的CALL
原理:实现的思路:把需要执行的函数fn和需要改变的this指向obj关联起来-> obj.xxx=fn,
此时我们只需要obj.xxx(),就相当于把fn执行,而且函数中的this就是obj
实现代码:
自己封装的call方法
优化:
1.临时添加的属性不能和原始对象中的属性冲突
2.参数的处理,传入的context如果为空或者传入的为undefined或者null,以及传入的context不是引用数据类型的需要进行转化,因为基本数据类型无法添加属性
Function.prototype._call = function _call(context, ...parms) {
// 下面执行_call方法时,点前面是fn,所以this是fn (17行)
context == null ? (context = window) : null; //如果为空或者什么都不传就把context赋值为window,否则就什么都不做
/^(object|function)$/.test(typeof context) ? null: (context = Object(context)); //如果传入的context不是引用类型,转换为引用类型
let xxx = Symbol(); //保证添加的属性的唯一性
context[xxx] = this; //给对象添加一个属性,指向需要执行的函数,此刻的this是fn
let result = context[xxx](...parms); //执行函数,传入剩余参数
delete context[xxx]; //删除添加的属性,不改变原始数据结构
return result; //把结果返回出去
};
let res = fn._call(null, 30, 10);
四、bind的用法
fn.bind(context[, arg1[, arg2[, …]]])
bind:函数不会立即执行,预先处理函数中的this和参数,返回的是一个函数体
function fn(x,y){
console.log(this, x, y);
}
let obj = {
id:'11',
name:'邱顺俊',
};
document.body.onclick = fn;
//=> this:document.body
需求:当点击BODY时,让fn执行,并且this->obj,传递值10->x、20->y
document.body.onclick = function (ev){
//=> 当触发BODY的点击事件时
//=> 执行的是这个匿名函数
//=> 这里 this:body;
//=> 然后,实现上面的需求:
fn.call(obj, 10, 20, ev);
};
//=> 或者直接用bind,也能实现相同的效果
document.body.onclick = fn.bind(obj, 10, 20);
△ bind不会让函数立即执行的,执行点击事件执行
五、重写内置的BIND
//实现bind方法,返回的是一个函数
Function.prototype._bind = function _bind(context, ...parms) {
let that = this;
return function (...arg) {
context == null ? context = window : null;
/^(function|object)$/.test(context) ? null : context = Object(context);
let xxx = Symbol();
parms=parms.concat(arg);
context[xxx] = that;
let result = context[xxx](...parms);
delete context[xxx];
return result;
}
}
或者
Function.prototype.bind = function (context, ...parms){
let self = this;
return function (...arg){
return self.call(context, ...parms.concat(arg));
};
};