谈起this的指向,是实际应用中比较常见的使用,同时也是面试中最多见的问题;在实际的应用中,咱们经过Vue
的this去调用方法,得到属性,在React
的生命周期写法中,经过将函数先bind
内部this,而后经过this.函数名
调用函数;javascript
this
是在调用的时候才被动态建立的this
的指向取决于当前被调用的上下文;
this
指向window;this
指向当前对象所在的this;this
的指向,则指向被更改的对象;var a = '333'
function g_fun(){
console.log(this) // Window
console.log("定义在全局的函数",this.a) ;// '333'
}
g_fun() ;
var obj={
a:'对象内部的a',
g_fun:function(){
console.log(this.a) //'对象内部的a'
}
}
obj.g_fun() //
复制代码
⚠️:若是全局函数是用let
进行定义的变量,在函数中是没有办法经过this.变量
访问的,let定义在全局的变量,没有办法挂载到this
中,可是能够经过变量名的方式进行访问;java
var
定义的变量挂载到this/window
中let
定义的变量不会挂载到this/window
中let b = 'mfy'
var b1 = 'mfy'
function g_funb(){
console.log(this.b) //underfined
console.log(b);//mfy
console.log(this.b1) //mfy
}
console.log(this)
g_funb()
复制代码
箭头函数无this,而内部的继承父执行上下文里面的this;
面试
let arrowFnn = ()=>{
console.log(this) // window
}
var objfn = {
name:'ee',
arrowFnn:()=>{
console.log(this) //window
}
}
复制代码
箭头函数找this
的指向,只须要按照层级一层一层向上查找,找到第一个非箭头函数,若是无则this
指向全局;markdown
var name = 2;
let funn = {
name:'mfy',
printName:()=>{
var name = 4;
console.log(name) // 4
console.log(this.name) //2
},
printName2:function(){
let name = 'fff'
console.log(this) // funn
console.log(this.name) //mfy
}
}
funn.printName();
funn.printName2();
复制代码
分别执行printName
函数,查看打印的内容;app
funn.printName
this指向window
name
在函数内部局部做用域和全局
都存在this
,打印windowfunn.printName2()
具名函数,this
指向当前调用者obj
, 就是obj
函数
变量this.name
直接获取当前this下的值oop
根据此面试题还会衍生出其余的面试题目ui
var
使用let
定义funn.printName
内部的this
进行更改在一些场景中,咱们须要更改函数的内部this,去实现咱们的相关需求;更改this方式最多的就是call、bind、apply
函数操做中一般用来更改this指向this
call、apply、bind
均可以更改this
,或者执行当前函数;call、apply
都是改变this
的指向,做用相同,只是传值的参数不一样;var obj ={
value:22,
}
function list(name,age){
console.log(this.value)
}
list.call(obj,'33',33)
复制代码
绑定this,并执行当前函数spa
Function.prototype.myCall=function(context){
//context是当前传入的对象或者其余想要绑定的this
var context = context || window;
context.fn = this;
//取出当前的this
var args =[...arguments].slice(1);
//调用当前的函数
var result = context.fn(...args);
//删除挂在实例上的方法
delete context.fn;
//返回调用的结果值
return result;
}
复制代码
var obj ={
value:22,
}
function list(name,age){
console.log(this.value)
}
list.call(obj,'33',33)
list.apply(obj,['33',33])
复制代码
Function.prototype.myApply=function(context){
var context = context || window;
context.fn = this;
var result = null;
//判断是否有参数传入
if(arguments[1]){
// 将参数进行分割开
result = context.fn(...arguments[1])
}else{
result = context.fn()
}
delete context.fn;
return result;
}
复制代码
bind 和 call、apply 不相同点在于,能够绑定函数,可是不会当即执行
this的指向
首先是进行bind的使用分析
var obj = {
a:2,
b:4
}
function demo(a,b){
console.log(...arguments)
console.log(a,b)
return false
}
let fun = demo.bind(obj,5)
console.log(fun.name); // 'bound demo'
console.log(fun.bind.name); // 'bind'
console.log(fun.bind); // 'bind'
console.log((function(){}).bind().name); // 'bound '
console.log((function(){}).bind().length); // 0
复制代码
bind
进行绑定的this的值返回一个bound
的函数若是返回的fun
在进行实例化函数呢?
var obj = {
a:2,
b:4
}
function demo(a,b){
console.log(...arguments)
console.log(a,b)
return false
}
let fun = demo.bind(obj,5)
var demom = new fun(6);
console.log(demom,'demom') //demo {} 'demom'
复制代码
new fun
返回的是demo原生构造器的新对象经过上面的实例进行分析bind
的功能
[[Prototype]]
(也就是__proto__
)连接。[[Prototype]]
连接到这个函数的prototype对象上。Object(包含Functoin, Array, Date, RegExg, Error)
,那么new表达式中的函数调用会自动返回这个新的对象。6.返回当前的bound
Function.prototype.myBindDemo = function (context) {
//1. 获取调用的函数
let fn = this;
//2. 分离参数bind时候传入的参数
let args = [].slice.call(arguments, 1);
//3.定义一个bound函数
function bound() {
//3.1 合并调用的参数和当前传入的参数
let currArgs = args.concat([].slice.call(arguments,0)) ;//合并全部的参数
// 3.2 判断是不是new的操做
if(this instanceof bound){
//3.3 建立一个全新的对象 ->而且执行[[Prototype]]__proto__连接->连接到这个函数的`prototype`对象上。断开当前的原型链
if(fn.prototype){
function Empty() {} //建立一个函数
Empty.prototype = fn.prototype; //该函数指向原来函数的this
bound.prototype = new Empty(); //脱离当前的原型链,将该bound指向其余
}
//3.4 生成的新对象会绑定到函数调用里面的this
let result = fn.call(this,...currArgs)
var isObject = typeof result === 'object' && result !== null;
var isFunction = typeof result === 'function';
if(isObject || isFunction){
return result;
}
// 返回当前call的函数
return this;
}else{
// apply修改this指向,把两个函数的参数合并传给self函数,并执行self函数,返回执行结果
return fn.apply(context, currArgs);
}
}
return bound;
}
复制代码
Function.prototype
的一个属性,它是一个函数,修改this指向,合并参数传递给原函数,返回值是一个新的函数。this
指向应用题判断this
指向的方式