談起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
指向的方式