開始看到JavaScript中的apply和call函數,很是不解。也看過幾篇文章可是一到實踐用到的時候又遺忘了。本文結合實例,當作筆記記錄一下該問題與你們分享。vue
apply:方法能劫持另一個對象的方法,繼承另一個對象的屬性.(具體是什麼意思呢?咱們看看下面的例子就知道啦)程序員
apply()在w3c手冊是這樣描述的:數組
經過 apply() 方法,您可以編寫用於不一樣對象的方法。app
不一樣之處是:函數
call() 方法分別接受參數。ui
apply() 方法接受數組形式的參數。this
若是要使用數組而不是參數列表,則 apply() 方法很是方便。spa
簡單的來講,call()是apply()的一顆語法糖,做用和 apply() 同樣,一樣可實現繼承,惟一的區別就在於call()接收的是參數列表,而apply()則接收參數數組。3d
一個簡單的實例,但願你們也能夠理解數據的關係,文末還有一個小問題,知道答案的話也就基本理解了apply啦。code
使用 apply, 你能夠繼承其餘對象的方法:
var max = Math.max.apply(null, [1, 2, 3, 4, 5]); console.log(max); // 輸出5
注意這裏apply()的第一個參數是null,在非嚴格模式下,第一個參數爲null或者undefined時會自動替換爲指向全局對象,apply()的第二個參數爲數組或類數組。
使用call:
var max = Math.max.call(null, 1, 2, 3, 4, 5); console.log(max); // 輸出5
來看w3c上的示例:
var person = { fullName: function(city, country) { return this.firstName + " " + this.lastName + "," + city + "," + country; } } var person1 = { firstName:"John", lastName: "Doe" } person.fullName.apply(person1, ["Oslo", "Norway"]); // person.fullName.call(person1, "Oslo", "Norway"); // call
以上代碼的結果是 。咱們發現 對象person1 傳遞到了 person 的 fullName 方法內,結果能說明:apply()方法能劫持另一個對象的方法,繼承另一個對象的屬性.
(本例子在vue項目中實現)
例1:
test.vue 頁面上寫一個按鈕 按鈕點擊觸發 btnclick(),咱們能夠看到在方法內有一個person類,有一個student類。對比控制檯輸出,咱們能夠發現。
最後一行''444444'輸出的this,是vue對象。能夠理解
student內的this,是當前student對象。也能夠理解
person內的this,就是student對象。 爲何?
緣由是由於在student內apply的使用Person.apply(this,arguments)。此時person.apply把student內當前對象劫持並繼承該對象
apply:方法能劫持另一個對象的方法,繼承另一個對象的屬性.
btnclick () { function Person (name, age) { console.log(name, age, '1111111111111') // 控制檯輸出 jack 24 1111111111111 console.log(this, '33333333333') // 控制檯輸出 Student {} "33333333333" this.name = name this.age = age } function Student (name, age, grade) { Person.apply(this,arguments) console.log(this) // 控制檯輸出 Student {name: "jack", age: 24} console.log(arguments) // 控制檯輸出 Arguments(3) ["jack", 24, "2年"] this.grade = grade; } const stu = new Student("jack", 24, "2年") console.log(stu, '2222222222') // 控制檯輸出 Student {name: "jack", age: 24, grade: "2年"} "2222222222" console.log(this, '4444444444') // 控制檯輸出 VueComponent {_uid: 9, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …} "4444444444" }
例2:
test.vue 頁面上寫一個按鈕 按鈕點擊觸發 btnclick2(),咱們能夠看到在方法內只有一個person類。對比控制檯輸出,咱們能夠發現。
person內的this輸出爲當前vue對象,與上面對比的不一樣之處在於,例1中的person.apply()是在student內使用的,而當前例子的person.apply()是在點擊按鈕方法內直接觸發的,因此對象this也就變成了當前對象this,即vue實例。
btnclick2 () { function Person (name, age) { console.log(name, age, '1111111111111') // 控制檯輸出 jack 18 1111111111111 console.log(this, '33333333333') // VueComponent {_uid: 9, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …} "33333333333" this.name = name this.age = age } const params = ["jack", 18] Person.apply(this,params) console.log(this) // VueComponent {_uid: 9, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …} }
整文件代碼以下,能夠看到頁面還會輸出name,age,grade。
<template> <div class="hello"> <div> <button @click="btnclick()">觸發函數</button> <button @click="btnclick2()">觸發函數2</button> </div> <div>{{ name }}</div> <div>{{ age }}</div> <div>{{ grade }}</div> </div> </template> <script> export default { name: 'HelloWorld', props: { msg: String }, data () { return { name: '', age: '', grade: '' } }, methods: { btnclick () { function Person (name, age) { console.log(name, age, '1111111111111') console.log(this, '33333333333') this.name = name this.age = age } function Student (name, age, grade) { Person.apply(this,arguments) console.log(this) console.log(arguments) this.grade = grade; } const stu = new Student("jack", 24, "2年") console.log(stu, '2222222222') console.log(this, '4444444444') }, btnclick2 () { function Person (name, age) { console.log(name, age, '1111111111111') console.log(this, '33333333333') this.name = name this.age = age } const params = ["jack", 18] Person.apply(this,params) console.log(this) } } } </script> <style scoped> </style>
這兩個方法很好地體現了js函數式語言特性,在js中幾乎每一次編寫函數式語言風格的代碼,都離不開call和apply,可以熟練運用它們,是真正成爲一名jser程序員的重要一步。