# 一 、bind 特點: ### 1.返回原函數的拷貝,我們稱這個拷貝的函數為綁定函數 ### 2.將函數中的this固定為調用bind方法時的第一個參數,所以稱之為綁定函數。注意是名詞而非動詞。 ### 3.以后無論由哪個對象調用綁定函數,綁定函數中的this依然由當時調用的bind方法的一個參數決定,不會改變。 ### 4.如果綁定函數作為構造函數來使用,那么已經固定了的this將不會生效,此時構造函數中的this依然為實例對象。 ### 5.調用bind方法時的第二個參數做為綁定函數的第一個參數,稱之為預設參數,調用綁定函數時的第一個參數則排在預設參數后面 ### 6.無論使用任何對象調用bind方法時如果不傳參數、第一個參數為undefined、第一個參數為null時,綁定函數中的this指向window對象
作用: ### 1.拷貝一個目標函數 ### 2.改變綁定函數運行時的this指針
1-1 證明是原函數的拷貝 (需要知道:函數也是對象,並且是引用類型,比較的是內存地址) ``` function fn(){}
var bindFn = fn.bind(); //ƒ fn(){ return this } 供以后調用
fn === bindFn //false
<br>
<br>
2-1 將函數中的this固定為調用bind方法時的第一個參數
function fn(){ return this }
var bindFn = fn.bind({name:"綁定函數"}) //ƒ fn(){ return this }
<br>
<br>
3-1 以后無論由哪個對象調用綁定函數,綁定函數中的this依然是{name:"綁定函數"}
function fn(){ console.log(this) }
var bindFn = fn.bind({name:"綁定函數"})
bindFn() //等同於window對象調用 , this依然指向{name:"綁定函數"}
var obj = {name:"obj"};
obj.fn = bindFn;
obj.fn() //由普通對象調用 ,this依然指向{name:"綁定函數"}
var arr = [bindFn];
arr0 //由數組調用 , this依然指向{name:"綁定函數"}
setTimeout(bindFn , 200); //作為回調函數 , this依然指向{name:"綁定函數"}
clearTimeout(1);
<br>
<br>
4-1 如果綁定函數作為構造函數,已經捆綁的this會被忽略掉,this依然指向實例對象
function Person(name){
this.name = name;
}
var bindPerson = Person.bind({name:"綁定函數"})
new bindPerson("張三") // Person {name: "張三"}
<br>
<br>
5-1 預設參數
function fn(a,b,c,d){
console.log(a,b,c,d) // 1 ,2 ,3 ,4
}
var bindFn = fn.bind({name:"綁定函數"} , 1 ,2); // 拷貝原函數時的第2個參數開始往后稱為預設參數
bindFn(3,4); //調用綁定函數時的第一參數則排在預設參數的后面
<br>
<br>
6-1 當沒有參數、第一個參數為undefined、第一個參數為null時
var obj = {
fnOne:function(){ return this }.bind(),
fnTwo:function(){ return this }.bind( undefined ),
fnThree:function(){ return this }.bind( null )
}
//注意:這三種情況是使this指向window對象,而不是不去改變this指向,所以這里的this還是不會指向obj
obj.fnOne() // window
obj.fnTwo() //window
obj.fnThree() //window
<br>
<br>
<br>
# 二、call
特點:
### 1.返回值取決於目標函數的返回值
### 2.用call的第一個參數對象來代替調用目標函數的對象,以此來改變目標函數體內的this指向
### 3.調用call方法時的第二個參數做為目標函數的第一個參數,將第二個作為第三個以此類推
<br>
作用:
### 1.用於繼承,例如子構造函數繼承父構造函數
### 2.改變綁定函數運行時的this指針。
<br>
1-1 返回值取決於目標函數的返回值
function fn(){ return {name:"call"} }
fn.call() // {name: "call"}
<br>
<br>
2-1 改變目標函數體內的this指向 , 相當於使用第一個參數對象調用
function fn(){ return this }
fn.call( { name : "call" } ) // {name: "call"}
<br>
<br>
3-1 參數位置
function fn(a, b, c){ return arguments }
fn.call( { name : "call" } , 1 , 2 , 3 ) //Arguments [1, 2, 3]
<br>
<br>
1-2 用於繼承
function parent(name, age) {
this.name = name;
this.age= age;
}
function child(name, age) {
parent.call(this, name, age);
this.class = '三年級二班';
}
var xiaoming = new child("小明" , 18)
<br>
<br>
<br>
# 三、apply
特點:
### 1.與call方法一樣唯一不同的地方就是apply的第二個參數是一個數組,數組的第一個元素對應目標函數的第一個參數,以此類推
<br>
作用:
### 1.與call方法一樣
<br>
1-1 參數
function fn(a, b, c){ return a+b+c }
fn.apply({name:"apply"} ,[1,2,3]) //6
<br>
<br>
<br>
## 總結
### 相同點
####1. 3個方法都是改變綁定函數運行時的上下文
### 不同點
####1.bind方法的返回值是原函數的拷貝,供以后調用 。參數既可以在拷貝時預設又可在調用時添加
####2.call與apply一樣,返回值取決於目標函數的返回值 , 則是立即調用
####3.call與apply唯一的區別是call從第二個參數開始是若干個參數,而apply第二個參數是一個數組