摘要:的區(qū)別接收數(shù)組一連串參數(shù)返回一個函數(shù)的使用場景將類數(shù)組含有屬性的對象轉(zhuǎn)化為數(shù)組類數(shù)組例如通過獲取的元素含有屬性的對象具有屬性,并且可以通過下標(biāo)來訪問其中的元素,但是沒有中的等方法。
call,apply,bind的區(qū)別
apply接收數(shù)組 func.apply(obj, [arus])
call一連串參數(shù) func.call(obj, param1, param2....)
bind返回一個函數(shù) func.bind(obj,param...)(parms...)
call,apply,bind的使用場景
將類數(shù)組/含有l(wèi)ength屬性的對象轉(zhuǎn)化為數(shù)組
類數(shù)組:(例如通過document.getElementsByTagName獲取的元素、含有l(wèi)ength屬性的對象)具有l(wèi)ength屬性,并且可以通過0、1、2…下標(biāo)來訪問其中的元素,但是沒有Array中的push、pop等方法。
注意:但是這個不適用于IE6~8,會報錯,只能使用循環(huán)來解決
// 類數(shù)組 let trueArr = Array.prototype.slice.call(arrayLike) // 含有l(wèi)ength屬性的對象 let obj4 = { 0: 1, 1: "thomas", 2: 13, length: 3 // 一定要有l(wèi)ength屬性 }; console.log(Array.prototype.slice.call(obj4)); // [1, "thomas", 13]
求數(shù)組中的最大和最小值
注意:邊界問題,臨界值大概在 [ 參數(shù)個數(shù)限制在65536]
let arr = [1,2,3,89,46] let max = Math.max.apply(null,arr)//89 let min = Math.min.apply(null,arr)//1
數(shù)組追加
數(shù)組方法contact比較:contact返回新數(shù)組,不修改原數(shù)組
let arr1 = [1,2,3] let arr2 = [4,5,6] let total = [].push.apply(arr1, arr2) //6
利用call和apply做繼承
function Person(name,age){ // 這里的this都指向?qū)嵗? this.name = name this.age = age this.sayAge = function(){ console.log(this.age) } } function Female(){ Person.apply(this,arguments)//將父元素所有方法在這里執(zhí)行一遍就繼承了 } let dot = new Female("Dot",2)
判斷變量類型
function isArray(obj){ return Object.prototype.toString.call(obj) == "[object Array]" } isArray([]) // true isArray("dot") // false
其他:使用 log 代理 console.log
function log(){ console.log.apply(console, arguments); } // 當(dāng)然也有更方便的 let log = console.log()bind 實(shí)現(xiàn)
特點(diǎn):
返回一個函數(shù)
可以傳入?yún)?shù)(使用bind時和bind新生成的函數(shù)都可以傳參)
當(dāng) bind 返回的函數(shù)作為構(gòu)造函數(shù)的時候,bind 時指定的 this 值會失效,但傳入的參數(shù)依然生效
var bindFoo = bar.bind(foo, "daisy"); var obj = new bindFoo("18");
注意:bind這個方法在IE6~8下不兼容
// 使用apply和call來實(shí)現(xiàn)this指向問題 Function.prototype.bind2 = function (context) { if (typeof this !== "function") { throw new Error("what is trying to be bound is not callable"); } var self = this; // 獲得bind的參數(shù)從第二個參數(shù)到最后一個參數(shù) var args = Array.prototype.slice.call(arguments, 1); var fNOP = function () {}; var fBound = function () { // 指bind返回的函數(shù)傳入的參數(shù) var bindArgs = Array.prototype.slice.call(arguments); // 當(dāng)作為構(gòu)造函數(shù)時,this 指向?qū)嵗?,此時結(jié)果為 true,將綁定函數(shù)的 this 指向該實(shí)例,可以讓實(shí)例獲得來自綁定函數(shù)的值 // 以上面的是 demo 為例,如果改成 `this instanceof fBound ? null : context`,實(shí)例只是一個空對象,將 null 改成 this ,實(shí)例會具有 habit 屬性 // 當(dāng)作為普通函數(shù)時,this 指向 window,此時結(jié)果為 false,將綁定函數(shù)的 this 指向 context // new bind返回的函數(shù),this失效,但傳入的參數(shù)生效 return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs)); } // fBound.prototype = this.prototype; // 保證繼承,原型鏈,讓 fBound 構(gòu)造的實(shí)例能夠繼承綁定函數(shù)的原型中的值,下面兩行代碼等同于Object.creater() fbound.prototype = Object.create(this.prototype); // 我們直接修改 fBound.prototype 的時候,也會直接修改綁定函數(shù)的 prototype。這個時候,我們可以通過一個空函數(shù)來進(jìn)行中轉(zhuǎn) fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; } // es6實(shí)現(xiàn) Function.prototype.bind = function(context) { if(typeof this !== "function"){ throw new TypeError("not a function"); } let self = this; let args = [...arguments].slice(1); function Fn() {}; Fn.prototype = this.prototype; let bound = function() { let res = [...args, ...arguments]; //bind傳遞的參數(shù)和函數(shù)調(diào)用時傳遞的參數(shù)拼接 context = this instanceof Fn ? this : context || this; return self.apply(context, res); } //原型鏈 bound.prototype = new Fn(); return bound; }call 實(shí)現(xiàn)
實(shí)現(xiàn)思路
將函數(shù)設(shè)為對象的屬性 foo.fn = bar
執(zhí)行該函數(shù) foo.fn()
刪除該函數(shù) delete foo.fn
注意的點(diǎn)
接受不定長參數(shù) - Arguments 對象中取值,第二個到最后一個參數(shù),然后放到一個數(shù)組里
this 參數(shù)可以傳 null,當(dāng)為 null 的時候,視為指向 window
函數(shù)是可以有返回值的!
難點(diǎn)解析 - 接受不定長參數(shù)
var args = []; // 為了拼出一個參數(shù)字符串,arguments類數(shù)組,不能使用 for(var i = 1, len = arguments.length; i < len; i++) { // args: ["arguments[1]", "arguments[2]", .....] args.push("arguments[" + i + "]"); } // 1. context.fn(args.join(",")) es6語法實(shí)現(xiàn)es3的call方法不合適 // 2. 這里 args 會自動調(diào)用 Array.toString() 這個方法 // 3. eval作用:看成是