例一
var name = '小王',
age = 17;
var obj = {
name: "小張",
thisCopy: this, //this指向 window
objAge: this.age, //this指向window
myFun: function() {
console.log("obj-this", this) //this指向obj,obj沒有age這個(gè)屬性
// console.log(this.name + "年齡" + this.age)
}
}
console.log(obj)
console.log(this.age);//這個(gè)this指向window
console.log(obj.objAge) //17
obj.myFun(); //小張年齡 undefined
例2
var fav = "盲僧"
function shows() {
//console.log("shows-this", this) //this指向window
console.log(this.fav)
}
shows() //盲僧
比較一下這兩者 this 的差別展姐,第一個(gè)打印里面的 this 指向 obj躁垛,第二個(gè)全局聲明的 shows() 函數(shù) this 是指向window ;
1圾笨,call()教馆、apply()、bind() 都是用來重定義 this 這個(gè)對(duì)象的擂达!
var name = '小王',
age = 17;
var obj = {
name: "小張",
objAge: this.age,
myFun: function() {
console.log("obj-this", this) //this指向obj
console.log(this.name + "年齡" + this.age)
}
}
var db = {
name: "德瑪",
age: "89"
}
obj.myFun();//小張年齡underfind myFun的this指向obj
var myFunA= obj.myFun;
//myFunA在外部調(diào)用土铺,此時(shí)的this指向了全局對(duì)象
myFunA();//小王年齡17
//為了保證this指向不變,我們可以通過bind方法綁定this指向
//如:
var myFunA2= obj.myFun.bind(obj);
console.log(myFunA2()); //小張年齡underfind 需要調(diào)用才執(zhí)行
//此時(shí)可以看到this的指向保持指向了obj這個(gè)對(duì)象。
var myFunA3 = obj.myFun.call(obj);
console.log(myFunA3 ); //小張年齡underfind 不需要調(diào)用就執(zhí)行
var myFunA4 = obj.myFun.apply(obj);
console.log(myFunA4); //小張年齡underfind 不需要調(diào)用就執(zhí)行
//此時(shí)你會(huì)發(fā)現(xiàn)當(dāng)我們用call或者apply方法來保證this指向的時(shí)候悲敷,
//call和apply方法會(huì)直接執(zhí)行掉myFun這個(gè)方法究恤,不需要調(diào)用。
//obj.myFun方法里的this由obj指向db
obj.myFun.call(db) // 德瑪年齡 89
obj.myFun.apply(db) // 德瑪年齡 89
console.log(obj.myFun.bind(db)) //bind 返回的是一個(gè)新的函數(shù)后德,你必須調(diào)用它才會(huì)被執(zhí)行部宿。
obj.myFun.bind(db)() //調(diào)用bind返回的函數(shù) // 德瑪年齡 89
以上出了 bind 方法后面多了個(gè) () 外 ,結(jié)果返回都一致瓢湃!
由此得出結(jié)論理张,bind和call,apply的區(qū)別绵患,bind 返回的是一個(gè)新的函數(shù)雾叭,.只會(huì)改變函數(shù)this指向不會(huì)執(zhí)行函數(shù),你必須調(diào)用它才會(huì)被執(zhí)行落蝙,call和apply會(huì)改變this指向并且直接執(zhí)行了函數(shù)
2织狐,對(duì)比call 、bind 筏勒、 apply 傳參情況下
var name = '小王',
age = 17;
var obj = {
name: "小張",
objAge: this.age,
myFun: function(fm, ft) {
console.log("obj-this", this) //this指向obj
console.log(this.name + "年齡" + this.age, " 來自 " + fm + " 去往 " + ft)
}
}
var db = {
name: "德瑪",
age: "89"
}
obj.myFun.call(db, "廣州", "深圳") //德瑪年齡89 來自 廣州 去往 深圳
obj.myFun.apply(db, ["廣州", "深圳"]) // 德瑪年齡89 來自 廣州 去往 深圳
obj.myFun.bind(db, "廣州", "深圳")() //德瑪年齡89 來自 廣州 去往 深圳
obj.myFun.bind(db, ["廣州", "深圳"])() //德瑪年齡89 來自 廣州,深圳 去往 undefined
//例2
var obj = {
a:2,
sum:function(b,c){
return this.a + b + c;
}
}
var sum0 = obj.sum;
//分別用bind移迫,call,apply方法來調(diào)用sum0方法管行。
var sum1 = sum0.bind(obj,2,3);
console.log(sum1()); // 7
var sum2 = sum0.call(obj,2,3);
console.log(sum2); // 7
var sum3 = sum0.apply(obj,[2,3]);
console.log(sum3); // 7
從這里我們可以看出bind和call方法傳入?yún)?shù)方式和apply方式不一樣起意。
// 微妙的差距!
//
// 從上面四個(gè)結(jié)果不難看出:
//
// call 病瞳、bind 、 apply 這三個(gè)函數(shù)的第一個(gè)參數(shù)都是 this 的指向?qū)ο蟊幔诙€(gè)參數(shù)差別就來了:
//
// call 的參數(shù)是直接放進(jìn)去的套菜,第二第三第 n 個(gè)參數(shù)全都用逗號(hào)分隔,直接放到后面 obj.myFun.call(db,'成都', ... ,'string' )设易。
//
// apply 的所有參數(shù)都必須放在一個(gè)數(shù)組里面?zhèn)鬟M(jìn)去 obj.myFun.apply(db,['成都', ..., 'string' ])逗柴。
//
// bind 除了返回是函數(shù)以外,它 的參數(shù)和 call 一樣顿肺。
//
// 當(dāng)然戏溺,三者的參數(shù)不限定是 string 類型,允許是各種類型屠尊,包括函數(shù) 旷祸、 object 等等!
總結(jié):
call和bind方法可以傳入多個(gè)參數(shù)讼昆,第二個(gè)參數(shù)后的所有參數(shù)都傳入調(diào)用的函數(shù)中托享,apply方法只能傳入兩個(gè)參數(shù),且第二參數(shù)為數(shù)組,數(shù)組里面的元素傳入到調(diào)用的函數(shù)中闰围。
最后赃绊,我們考慮一下,如果使用apply方法時(shí)羡榴,傳入的第一個(gè)參數(shù)是null時(shí)碧查,調(diào)用函數(shù)時(shí),會(huì)發(fā)生什么情況校仑,會(huì)不會(huì)報(bào)錯(cuò)呢忠售!
不多說,直接上例子
var A={
name:"我是小A",
fun:function(num,money){
console.log("大家好肤视! "+this.name+" 我有"+num+"張"+money+"塊")
}
}
var B = {
name:"我是小B"
}
var monies = [10,20];
name="我是小C"
A.fun.apply(null,monies); //大家好档痪! 我是小C 我有10張20塊
可以看到 如果第一傳入的參數(shù)是null的話,在函數(shù)提內(nèi)的this會(huì)指向全局對(duì)象邢滑,在瀏覽器中就是window腐螟。
所以可以總結(jié)出兩點(diǎn):
1.如果函數(shù)中有明確使用this,那么this就會(huì)指向傳入的第一個(gè)參數(shù)的作用域困后。
2.如果傳入的第一參數(shù)為null時(shí)乐纸,this就會(huì)指向全局的作用域。
fn.apply(this, arguments)將函數(shù)的屬性與方法進(jìn)行拷貝摇予,bai主要是實(shí)現(xiàn)類的繼承汽绢。
function Person(name) {
this.name = name;
console.log('Person',this) //這里的this指向xiaoming這個(gè)實(shí)例
this.sayname = function() {
console.log(this.name) //小明
}
}
function Student(name) {
console.log("arguments",arguments);//arguments 是函數(shù)參數(shù)組成的一個(gè)數(shù)組,類數(shù)組
console.log('Student',this) //這里的this指向Student這個(gè)實(shí)例
//apply將Person方法里的this指向由window指向xiaoming這個(gè)實(shí)例侧戴,并且直接執(zhí)行
Person.apply(this, arguments); //調(diào)用person并且把this指向Student宁昭,同時(shí)把Student的參數(shù)傳過去,arguments是一個(gè)數(shù)組來的
}
var xiaoming = new Student("小明");
xiaoming.sayname();
//這樣Student類拷貝了Person的屬性和方法酗宋,實(shí)現(xiàn)了類的繼承
//忘記加上new命令,函數(shù)里面的this指向了全局作用域
部分轉(zhuǎn)自:https://www.runoob.com/w3cnote/js-call-apply-bind.html
js中arguments詳解
一积仗、簡(jiǎn)介
了解arguments這個(gè)對(duì)象之前先來認(rèn)識(shí)一下javascript的一些功能:
其實(shí)Javascript并沒有重載函數(shù)的功能,但是Arguments對(duì)象能夠模擬重載蜕猫。Javascrip中每個(gè)函數(shù)都會(huì)有一個(gè)Arguments對(duì)象實(shí)例arguments寂曹,它引用著函數(shù)的實(shí)參,可以用數(shù)組下標(biāo)的方式"[]"引用arguments的元素回右。arguments.length為函數(shù)實(shí)參個(gè)數(shù)隆圆,arguments.callee引用函數(shù)自身。
三翔烁、使用方法
雖然arguments對(duì)象并不是一個(gè)數(shù)組(類數(shù)組)渺氧,但是訪問單個(gè)參數(shù)的方式與訪問數(shù)組元素的方式相同
例如:
arguments[0],arguments[1],。租漂。阶女。arguments[n]颊糜; 在js中 不需要明確指出參數(shù)名,就能訪問它們
例如:
function test() {
var s = "";
for (var i = 0; i < arguments.length; i++) {
alert(arguments[i]);
s += arguments[i] + ",";
}
return s;
}
test("name", "age");
輸出結(jié)果:
name,age
我們知道每一個(gè)對(duì)象都有自己的屬性秃踩,arguments對(duì)象也不例外衬鱼,首先arguments的訪問猶如Array對(duì)象一樣,用0到arguments.length-1來枚舉每一個(gè)元素憔杨。下面我們來看看callee屬性鸟赫,返回正被執(zhí)行的** Function** 對(duì)象,guments.callee就是函數(shù)自身消别。,實(shí)現(xiàn)匿名的遞歸函數(shù)抛蚤。代碼如下:
var sum = function (n) {
if (1 == n) {
return 1;
} else {
return n + arguments.callee(n - 1); //6 5 4 3 2 1
}
}
alert(sum(6));
輸出結(jié)果:21
傳多個(gè)參數(shù)事可以直接用argument,比如求最大值:
function max() {
var max = arguments[0];
console.log(arguments)
for (val of arguments) {
if (val >= max) {
max = val;
}
}
return max;
}
var maxValue = max('9', 1, 2, 4)
console.log(maxValue)
//apply的另一種用法就是用于將數(shù)組分割為一個(gè)個(gè)元素寻狂。
//例如想在數(shù)組中a[1,2,3,4]中尋找出最大的袁術(shù)出來岁经。
//利用apply求最大值:
var a = [1, 2, 3, 4];
console.log(Math.max(a))
console.log(Math.max.apply(null, a)); //輸出4)