一、如何使用
this的四种指向:this 永远指向最后调用它的那个对象!!!
1、普通函数调用,指向window --- 如果是严格模式,指向undefined
function thisPoint() { console.log(this); } thisPoint(); //window function thisPointStrict() { 'use strict' console.log(this); } thisPointStrict(); //undefined
2、当this被obj.fn()调用时,指向obj.
var obj = { name: '测试this指向的类名字', fn() { console.log(this); } } obj.fn(); // obj 对象
3、call 改变this 的指向
function a(a, b, c) { name: 'a的名字'; console.log(this.name); console.log(a, b, c); } var b = { name: 'b的名字' } a.call(b, 1, 2, 3); //b的名字 1 2 3
4、apply改变this的指向
a.apply(b, [1, 2, 3]) //b的名字 1 2 3
总结 call和apply
相同点:
1、都是改变this指向的
使用区别:
1、call 第一个参数是this指向的对象,后边是参数列表
2、apply 第一个参数是this指向的对象,后边是参数数
5、bind改变this指向
bind会生成并且返回一个函数,这个函数的this指向第一个参数。
var c = a.bind(b, 1, 2, 3); c(); //b的名字 1 2 3
二、实现
1、call实现code
Function.prototype.mycall = function(context, ...arg) { const fn = Symbol('临时属性'); context[fn] = this; context[fn](...arg); delete context[fn]; } //思路: // 1、通过对象属性的方式调用函数,这个函数里面的this指向这个对象。 // 每次调用新增一个symbol属性,调用完毕删除。 // 这个symbol属性就是调用mycall方法的函数 //函数形参中使用 ...arg 是将多个形参塞到一个数组里面,在函数内部使用arg这个变量时,就是包含所以形参。 // 在调用context[fn](...arg) 时候,...arg是为了展开数组,依次传入参数调用函数。 var obj = { name: '测试的obj的名字' } function test(a, b, c) { console.log(this.name); console.log(a, b, c); } test.mycall(obj, 1, 2, 3)
2、apply实现code
Function.prototype.myApply = function(context, arg) { const fn = Symbol('属性'); context[fn] = this; context[fn](...arg); delete context[fn] } const obj2 = { name: '测试Obj2的名字' } function test(a, b, c) { console.log(this.name); console.log(a, b, c); } test.myApply(obj2, [2, 3, 4]) //总结 : // call 是传参的列表,所以一开始需要...arg; apply 是传参数组,不需要...arg
3、bind实现code
var obj = { name: '我是obj的名字' } function test(a, b, c) { name: '我是test的名字'; console.log(this.name); console.log(a, b, c); } // bind跟call和apply的区别: bind返回一个新的函数,并且不会调用。 call和apply会改变原函数的this指向,并且调用 Function.prototype.myBind = function(objThis, ...params) { const _this = this; let fToBind = function(...secoundarg) { const isNew = this instanceof fToBind; const context = isNew ? this : Object(objThis); return _this.call(context, ...params, ...secoundarg); } fToBind.prototype = Object.create(_this.prototype); return fToBind; } var fnbind = test.myBind(obj, 2, 3, 4) fnbind()