天天打call, 你可知道javascript中的call?

小5蟲子發表於2017-10-27

一說到call

————總是call、‘張三’、‘李四’的區別什麼什麼的,說的很清楚,轉身還是傻傻分不清楚他們的區別了,相似的事情總是喜歡一起來說,這對於新手來說總是容易混亂的,今天就來理解下call的用法;

通俗點:

call的作用就是: 改變函式執行時的上下文 也就是this的指向;

用法:

Food.call(thisArg, arg1, arg2, ...)複製程式碼

來看個例子 --- A

function fun(){
    this.name = 'fun-name'
    this.age = 'fun-age'
}
 var wrap = {
     age: 'default',
     name: 'default',
     myfun: function() {
         fun()
     }
}

wrap.myfun();
console.log(wrap.age)   // 'default-age'
console.log(window.age)  // 'fun-age'複製程式碼

直接執行這個函式 wrap.myfun();

執行這個函式後
1、在wrap下面執行myfun()後,其中的this指向window全域性的
2、在window全域性下面建立了一個 age屬性,值為 'fun-age'
3、wrap中的age還是default

來看個例子 --- B

function fun(){
    this.name = 'fun-name'
    this.age = 'fun-age'
}
 var wrap = {
     age: 'default',
     name: 'default',
     obj: function() {
         fun.call(this)      // **---注意這裡打 call 了---**
     }
}

wrap.myfun();
console.log(wrap.age)   // 'fun-age'        --發生了變化---
console.log(window.age)  // 'age is not defined'   --發生了變化---複製程式碼

例子B執行時:

wrap.obj()執行後,在執行fun時,把this, call進去了, 這個this是指向wrap,所以fun執行時其中的this指向的是wrap,自然改變的就是wrap中的age,這就是call的作用改變了fun執行時的上下文;

好累,反正我是大概懂了他(this)剛才幹了什麼;


那麼在我們的coding中,一般什麼時候用到call了?

1、利用call來 做繼承

var Person = function () {
    this.fun = function() { 
        console.log('longlee') }
};
var student = function () {
    Person.call(this);
};

var st = new student ();

g1.fun()  // 輸出: longlee複製程式碼

如果不在student函式中執行 call,new出來的例項是沒有fun屬性方法的;打call就可以實現繼承Person方法了;

2、判斷資料的型別 【object、 array、 null】

var obj1 = {name: 'longlee'}
var obj2 = ['longlee']
var obj3 = null

Object.prototype.toString.call(obj1)    // "[object Object]"
Object.prototype.toString.call(obj2)    // "[object Array]"
Object.prototype.toString.call(obj3)    // "[object Null]"
Object.prototype.toString.call(12)      // "[object Number]"
....
....複製程式碼

3、類(偽)陣列使用陣列方法

var arg = Array.prototype.slice.call(arguments);
arguments是函式接收的實際引數個數,他是一個偽陣列,不具有陣列的一般方法。比如 push、pop...,

但是我們能通過 Array.prototype.slice.call 轉換為真正的陣列
這樣 arguments 就可以應用 Array 下的所有方法了。複製程式碼

4、獲取陣列中的最大值和最小值

maxInNumbers = Math.max.call(Math, 55, 888 , 521 , -36); // 888
number 本身沒有 max 方法,但是 Math 有,我們就可以藉助 call 使用其方法。複製程式碼

就說到這了,再說下去,我自己也快消化不良了、、、、


題外話:
說到陣列的最大值、最小值。我控制不住自己了,一個ES6的簡潔方法
Math.max(...[2,1,3]) // 3
Math.min(...[2,1,3]) // 1

個人見解,有誤之處,大神請指出,以免改正!
弄懂 call 了。可以繼續打 call 了

相關文章