前言
影響因素
-
調(diào)用時輸入的參數(shù) params -
定義時的環(huán)境env
聲明一個函數(shù)
const f1 = new Function('x', 'y', 'return x+y')
function f2(x, y) {return x + y}
const f3 = function (x, y) {return x + y}
const f4 = (x, y) => x + y
其中f1 不常用,f2是聲明一個函數(shù)f2,const f3 和 const f4這兩個都不屬于函數(shù)聲明的部分,為什么要加上,因為f3 里面的函數(shù)是一個匿名函數(shù),如果沒有const f3 那么這個匿名函數(shù)聲明之后就找不到這個匿名函數(shù)了,所以必須聲明之后馬上賦值。f4 是最新的語法叫做箭頭函數(shù),括號里面的是參數(shù),然后返回x+y
f1、f2、f3是ES6之前的語法,支持this/arguments/new
而f4是ES6 新出的語法,不支持this/arguments/new
箭頭函數(shù)為何不支持this
const f =()=>console.log(this)
f() //Window
f.call({name:'小紅'}) //Window

看一下前言中函數(shù)的影響因素,一個是調(diào)用的參數(shù),一個是定義的環(huán)境。
在箭頭函數(shù)里面,this就是一個環(huán)境。
//代碼1
const a=233
const f2 =() => console.log(a)
//代碼2
console.log(this)
const f1 =() -> console.log(this)

箭頭函數(shù)如何處理a ,就如何處理this
即
箭頭函數(shù)把this當做外部的變量,僅此而已,但是非箭頭函數(shù)的this有很多的特殊處理
箭頭函數(shù)不支持 this 指的就是箭頭函數(shù)對this與其他的變量一視同仁,不會特殊對待
非箭頭函數(shù)的this
死記方法
- this是上下文
- 全局環(huán)境執(zhí)行函數(shù)時,this是全局對象
- 調(diào)用對象的方法時,this是該對象
- 函數(shù)里調(diào)用函數(shù)時,this是全局對象
- 箭頭函數(shù)里的this,不看調(diào)用,看定義(靜態(tài)作用域)
- 還有人說箭頭函數(shù)里的this指向外面的this
- 用new調(diào)用函數(shù)時,this是新增對象
- 可以用call/apply/bind指定this
this是參數(shù)還是環(huán)境?
答:this是一個參數(shù),它是一個隱性參數(shù)
this的確定
顯式this
- fn.call(asThis,1,2)
- fn.bind(asThis,1,2)()
- fn.method.call(obj,'hi')
隱式this
- fn(1,2) // fn.call(undefined,1,2)
- obj.method('hi') // obj.method.call('obj','hi')
- array0 //array[0].call('array','hi')


最后一個圖怎么理解?
array是一個數(shù)組,[f,"2"],array[0]是一個函數(shù)f,然后加上括號就是調(diào)用這個函數(shù)f ,所以最后打印出來的this就是 array ,p1就是傳入的參數(shù)hi。
測試一下
button.onclick =function (e){
console.log(this) //this是參數(shù),答 button 是錯誤的
}
正確答案就是 不知道
第一種情況,用戶點擊按鈕
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<button id="a">按鈕</button>
</body>
<script>
var button =document.getElementById('a')
button.onclick=function (e){
console.log(this)
}
</script>
</html>

答案的結(jié)果是button ,為什么會說這個答案是錯的呢?因為這里面沒有說用戶點擊這個按鈕,只是說了這段代碼
第二種情況 將button.onclick賦值給另一個變量,在調(diào)用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<button id="a">按鈕</button>
</body>
<script>
var button =document.getElementById('a')
button.onclick=function (e){
console.log(this)
}
var f =button.onclick
f()
</script>
</html>


解析:第一個就是不能確定this,第二個就是看調(diào)用的是誰
如何回答:這個this的值是無法確定,我們要看這次是如何調(diào)用的,如果是用戶點擊這個按鈕,那么瀏覽器就一定會把button作為參數(shù)傳進去。如果是通過其他方式調(diào)用的,就看它是怎么調(diào)用的。比如說:它聲明一個變量 f 等于這個 button.onclick ,然后調(diào)用,那么這次的瀏覽器就會把window作為參數(shù)傳入進去。如果你用其他方式,比如說 f.call('xiaohong'),那么瀏覽器傳入的就是字符串String
看下一個題目:
let length = 10
function fn() {
console.log(this.length)
}
let obj = {
length: 5,
method(fn) {
fn()
arguments[0]()
}
}
obj.method(fn, 1)
看不懂!看下一個代碼,將里面的 arguments[0]() 暫時去掉
let length = 10
function fn() {
console.log(this.length) //this 就是window ,window.length 就是看有多少個窗口或者iframe
}
let obj = {
length: 5,
method(fn) {
fn.call(undefined) //fn()
}
}
obj.method(fn, 1)
這個時候很確定這里面的this指的就是Window
let length = 10
function fn() {
console.log(this.length)
}
let obj = {
length: 5,
method(fn) {
arguments[0]()
}
}
obj.method(fn, 1)
將里面的 arguments[0]() 改為 arguments[0].call(arguments),傳進去的this可以確定是一個數(shù)組,那么arguments[0] 也就是執(zhí)行fn,可以改為arguments.0.call(arguments) 所以就是fn.0.call(arguments) 最后就是fn.call(arguments) ,又因為obj.method(fn, 1)輸入了兩個參數(shù),因此里面的arguments 代表的就是實參的長度,所以這里輸出的是2
總結(jié)
規(guī)則
this是call的第一個參數(shù)
new 重新設(shè)計了this、箭頭函數(shù)不接受this
記憶點
- 函數(shù)的返回值由參數(shù)和環(huán)境確定
- this是參數(shù),arguments也是參數(shù)
- 全局變量和自由變量是環(huán)境