this
this 是什么
-
如果来描述 this 的话:
-
当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。
- 我理解为 this 的 origin 实则是 this 如何生成(函数调用调用时(this 的指向完全取决于在哪里被调用并不是指向函数自身)),this 的生成必须有个父亲就是上文所说的函数(this 绑定的函数),然而函数则是 this 的关键,调用时间地点也很重要
-
这个记录会包含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。
- 我理解为 this 的 myself this 自身的一些信息(调用栈,父亲的方法,函数的参数)
-
this 就是记录的其中一个属性,会在函数执行的过程中用到。
- 我理解为 this 的 effect this 就是这个记录中的属性,this 使用的地方
-
为什么用 this
- this 提供了一种更优雅的方式来隐式“传递”一个对象引用,因此可以将 API 设计 得更加简洁并且易于复用。(说白了就是可以偷懒)使用时需要注意 this 的指向,尤其是回调函数中
function aa(ctx){
console.log(ctx.name)
}
function bb (){
console.log(this.name)
}
var ctx={name:"marco is dashuaibi"}
aa(ctx)
aa.call(ctx)
怎么用 this(解析)
怎么使用 this 呢,首先要先问自己 this 到底引用的是什么,也就是上文所说的父亲是谁,父亲在哪里造出的你(函数被调用的位置)
-
默认绑定(独立函数调用)。 this 是指向 window 的,如果在严格模式下(strict mode),this 则为 undefined
-
隐式绑定
function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; obj.foo(); // 2- 隐式丢失(被隐式绑定的函数会丢失绑定对象,从而把 this 绑定到全局对象或者 undefined 上)
-
显式绑定(这里就不讲解这两个方法了,会把对照的 polyfill 写下来)
- call
call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数 语法:function.call(thisArg, arg1, arg2, ...)
Function.prototype.myCall = function(thisArg, ...args) { const fn = Symbol('fn') // 声明一个独有的Symbol属性, 防止fn覆盖已有属性 thisArg = thisArg || window // 若没有传入this, 默认绑定window对象 thisArg[fn] = this // this指向调用call的对象,即我们要改变this指向的函数 const result = thisArg[fn](...args) // 执行当前函数 delete thisArg[fn] // 删除我们声明的fn属性 return result // 返回函数执行结果 }- apply
apply() 方法调用一个具有给定 this 值的函数,以及作为一个数组(或类似数组对象)提供的参数。 语法:func.apply(thisArg, [argsArray])
Function.prototype.myApply = function(thisArg, args) { const fn = Symbol('fn') // 声明一个独有的Symbol属性, 防止fn覆盖已有属性 thisArg = thisArg || window // 若没有传入this, 默认绑定window对象 thisArg[fn] = this // this指向调用call的对象,即我们要改变this指向的函数 const result = thisArg[fn](...args) // 执行当前函数 delete thisArg[fn] // 删除我们声明的fn属性 return result // 返回函数执行结果 }这两种方法我的理解就很像某鹅厂 这个游戏我做不了,我买下了也是我的(个人拙见)
- 硬绑定(bind)显示绑定的一种变形 > bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。语法: function.bind(thisArg, arg1, arg2, ...)常常用于柯里化 ``` 是 MDN 提供的polyfill if (!Function.prototype.bind) { Function.prototype.bind = function(oThis) { if (typeof this !== "function") { throw new TypeError( "Function.prototype.bind - what is trying " + "to be bound is not callable" ); } var aArgs = Array.prototype.slice.call( arguments, 1 ), fToBind = this, fNOP = function(){}, fBound = function(){ return fToBind.apply( ( this instanceof fNOP && oThis ? this : oThis ), aArgs.concat( Array.prototype.slice.call( arguments ) ); } ; fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; }; } ``` - new 绑定 1. 创建(或者说构造)一个全新的对象。 2. 这个新对象会被执行 [[ 原型 ]] 连接。 3. 这个新对象会绑定到函数调用的 this。 4. 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。 ``` function foo(a) { this.a = a; } var bar = new foo(2); console.log( bar.a ); // 2 ```优先级: bind > new > 隐式
- call
软绑定 (以实现和硬绑定相 同的效果,同时保留隐式绑定或者显式绑定修改 this 的能力。) softBind()
polyfill
if (!Function.prototype.softBind) {
Function.prototype.softBind = function(obj) {
var fn = this; // 捕获所有 curried 参数
var curried = [].slice.call( arguments, 1 );
var bound = function() {
return fn.apply( (!this || this === (window || global)) ? obj : this
curried.concat.apply( curried, arguments ) );
};
bound.prototype = Object.create( fn.prototype );
return bound;
};
}
- 对了还有一个最重要的 箭头函数的 this,箭头函数没有 this,箭头函数是根据外层(函数或者全局)作用域来决定 this,不能够使用应绑定.
- 箭头函数式没有prototype的,所以他的this在箭头函数被创建的时候就继承了外层的