this綁定規(guī)則萨蚕。
1酱虎、函數(shù)在調(diào)用時寨蹋,javascript會默認(rèn)給this綁定一個值
2松蒜、this的綁定和定義的位置(編寫的位置)沒有關(guān)系
3、this的綁定和調(diào)用方式以及調(diào)用的位置有關(guān)系
4已旧、this是在運行時被綁定的秸苗。
this有四種綁定規(guī)則:
分別為默認(rèn)綁定,隱式綁定运褪,顯式綁定惊楼,new綁定
規(guī)則一:默認(rèn)綁定
如下綁定方式都是默認(rèn)綁定玖瘸,
獨立函數(shù)調(diào)用時進(jìn)行默認(rèn)綁定,跟定義的位置沒有關(guān)系
// 案例一:
function foo(){
console.log(this) //window1
}
foo() //獨立調(diào)用
// 案例二:
function foo1(){
console.log(this)//window1
}
function foo2(){
console.log(this)//window1
foo1()
}
function foo3(){
console.log(this)//window1
foo2()
}
foo3()//獨立調(diào)用
// 案例三:
var obj = {
name:'why',
foo:function(){
console.log(this)
}
} //跟定義的位置沒有關(guān)系
var obj = obj.foo
obj() //調(diào)用的方式有關(guān)系檀咙,獨立調(diào)用雅倒。
// 案例四:
function foo(){
console.log(this) //window
}
var obj = {
name:'why',
foo:foo
}
var bar = obj.foo
bar() //調(diào)用的方式有關(guān)系,獨立調(diào)用弧可。
// 案例五:
function foo(){
return function(){
console.log(this) //window
}
}
var fn = foo()
fn() //調(diào)用的方式有關(guān)系蔑匣,獨立調(diào)用。
規(guī)則二:隱式綁定棕诵。
永遠(yuǎn)指向調(diào)用這個函數(shù)的對象裁良。
object對象會被js引擎綁定到fn函數(shù)中的this里面
// 案例一:
function foo(){
console.log(this)
}
var obj = {
name:'why',
foo:foo
}
obj.foo()
//案列二:
var obj ={
name:'xuan',
eating:function(){
console.log(this.name + "在吃東西")
}
}
obj.eating() //xuan在吃東西
var fn = obj.eating
fn() // 在吃東西 默認(rèn)調(diào)用,指向window
//案例三:
var obj1 = {
name:'obj1',
foo:function(){
console.log(this.name) //obj2
}
}
var obj2 = {
name:'obj2',
bar:obj1.foo
}
obj2.bar() //不管調(diào)用過程是怎樣的校套,只要是通過對象調(diào)用起來的价脾,就指向這個對象
規(guī)則三:顯式綁定(call,apply,bind)
call和apply的使用:
在隱式綁定中,必須在調(diào)用的對象內(nèi)部有一個對函數(shù)的引用笛匙,那如果不想在這個對象內(nèi)部引用函數(shù)侨把,那就必須通過call或apply來改變this指向。如下圖妹孙。obj中沒有引用函數(shù)座硕,可以通過call或apply來改變指向。
var name = 'xuan'
var obj = {
name:'obj'
}
function sum(){
console.log(this.name)
}
sum() //xuan
sum.call(obj) //obj
sum.apply(obj) //obj
bind的使用:
如下call要多次使用需每次都通過call來綁定涕蜂,而bind只需要直接調(diào)接收的這個變量即可华匾。
如下涉及到優(yōu)先級問題,隱式綁定大于window優(yōu)先級机隙,所以可以直接newFoo()
var obj ={name:'aa'}
function foo(){
console.log(this)
}
foo.call(obj)
foo.call(obj)
foo.call(obj)
foo.call(obj)
foo.call(obj)
foo.call(obj)
var newFoo = foo.bind(obj)
newFoo()
newFoo()
newFoo()
newFoo()
newFoo()
newFoo()
call與apply的區(qū)別:
區(qū)別就在于傳參方式不一樣蜘拉,call是逗號分隔傳,apply是存放到數(shù)組中一塊傳
var name = 'xuan'
var obj = {
name:'obj'
}
function sum(num1,num2,num3){
console.log(num1 + num2 + num3,this.name)
}
sum.call(obj,1,2,3) //6 'obj'
sum.apply(obj,[1,2,3]) //6 'obj'
call,apply 與bind 的區(qū)別 :
call和apply可以直接進(jìn)行改變有鹿,而bind必須有一個變量來接收才行
foo.call(obj)
foo.apply(obj)
//bind
var newFoo = foo.bind(obj)
newFoo()
規(guī)則四:new綁定
我們通過一個new關(guān)鍵字調(diào)用一個函數(shù)時(構(gòu)造器)旭旭,這個時候this是在調(diào)用這個構(gòu)造器時創(chuàng)建出來的對象,this = 創(chuàng)建出來的對象
function Person(name,age){
this.name = name
this.age = age
}
var p1 = new Person('xuan',15)
var p2 = new Person('xiang',16)
console.log(p1.name,p1.age) //xuan 15
console.log(p2.name,p2.age) //xiang 16
------------------------------------其他地方使用this的解析:----------------------------------------------
一葱跋、setTimout中的this:
//普通函數(shù)中的this是window
setTimeout(function(){
console.log(this) //window
},1000)
//箭頭函數(shù)中的this是由上級作用域來指向
setTimeout(()=>{
console.log(this) //window
},1000)
二持寄、監(jiān)聽點擊事件中的this
操作dom事件中的this指向當(dāng)前操作的dom元素
<div class="box"></div>
<script>
var box = document.querySelector('.box')
box.onclick = function(){
console.log(this) //<div class="box"></div>
}
</script>
三、數(shù)組高階函數(shù)中this
高階函數(shù)中this默認(rèn)指向window,可以有第二個參數(shù)娱俺,第二個參數(shù)就是改變當(dāng)前this的指向到它稍味。
var names = ['abc','cba','nba']
names.forEach(function(item){
console.log(this) //window
})
names.map(function(item){
console.log(this) //aaa
},'aaa')
-------------------------------------------------------------綁定規(guī)則優(yōu)先級----------------------------------------------------------
1、默認(rèn)規(guī)則下優(yōu)先級最低
2荠卷、顯式綁定>隱式綁定
call和apply:
var obj = {
name:'obj',
foo:function(){
console.log(this)
}
}
obj.foo() //obj
obj.foo.call('abc') //abc
obj.foo.apply('abc') //abc1
bind:
// 案例一
var obj = {
name:'obj',
foo:function(){
console.log(this)
}
}
var bar = obj.foo.bind('cba') //cba
bar()
// 案例二
function foo(){
console.log(this)
}
var obj = {
name:'obj',
foo:foo.bind('aaa')
}
obj.foo() // aaa
3模庐、new綁定 > 隱式綁定
var obj = {
name:'obj',
foo:function(){
console.log(this) // foo{}
}
}
var f = new obj.foo()
4、new 顯式綁定
new關(guān)鍵字不能和call/apply綁定,只能和bind一起用油宜。
new > bind
function foo(){
console.log(this) // foo{}
}
var bar = foo.bind('aaa')
var obj = new bar()
-------------------------------------------------------------thsi規(guī)則之外----------------------------------------------------------
一掂碱、忽略顯示綁定
當(dāng)在顯示綁定中將它指向unll或undefined中時指向的是window
function foo(){
console.log(this)
}
var obj = {
name:'why'
}
foo.call(null) //window
foo.apply(undefined) //window
var bar = foo.bind(null) //window
bar()
二怜姿、箭頭函數(shù)中this
箭頭函數(shù)中的this指向的是外層作用域使用的this。
var name = 'xxx'
var obj = {
name:'xuan',
getData:function(){
setTimeout(function(){
console.log(this.name) //xxx
},1000)
setTimeout(()=>{
console.log(this.name) //xuan
},1000)
}
}
obj.getData()
注:對象是沒有作用域的疼燥,所以下邊this.name指向的并不是person中的name沧卢,而是再外層的window
var name = 'window'
var person = {
name:'person',
foo:()=>{
console.log(this.name)
}
}
person.foo()