摘要:和相同點改變指向可以傳參立即調用區(qū)別接收一個數(shù)組參數(shù),直接接收參數(shù)的性能會比差,因為要對數(shù)組參數(shù)進行判斷和解構模擬實現(xiàn)傳遞的如果是或者,那么就是,否則傳遞進來的就是要指向的從第二個參數(shù)開始就是要調用時用到參數(shù)的第二個參數(shù)為數(shù)組,數(shù)組中的元素
call和apply
fn.call(isThis, arg1, arg2, ....)
fn.apply(isThis, [arg1, arg2, ....])
相同點:
改變 this 指向
可以傳參
立即調用
區(qū)別:
apply 接收一個數(shù)組參數(shù),call 直接接收參數(shù)
apply 的性能會比call差,因為要對數(shù)組參數(shù)進行判斷和解構
模擬實現(xiàn):
Function.prototype.callLike = function (isThis) { //... } Function.prototype.applyLike = function (isThis) { //... }
傳遞的 isThis 如果是 undefined 或者 null,那么 this 就是 window,否則傳遞進來的就是要指向的this
call 從第二個參數(shù)開始就是要調用時用到參數(shù)
apply 的第二個參數(shù)為數(shù)組,數(shù)組中的元素就是調用時用到參數(shù)
第一個條件很簡單,判斷下 isThis 的類型即可
isThis = typeof isThis === "undefined" || isNull(isThis) ? window : isThis; function isNull (value) { return typeof value === "object" && !value === true }
第二個條件和第三個條件是一樣的,call 的參數(shù)我們需要處理下,因為我們預期不到它的參數(shù)個數(shù)
我們從第二個參數(shù)開始遍歷一遍 arguments,然后放到一個數(shù)組里面去
var args = []; for (var i = 1, l = arguments.length; i< l; i++) { args.push(arguments[i]); }
但是最關鍵的調用怎么辦呢,怎么改變 this 的指向,一般來說誰調用誰就是 this,我們要想改變 this,那么就要用傳遞進來的 isThis 來調用
isThis.fn = this; isThis.fn(); delete isThis.fn;
這樣的話就改變了 this 的指向,之后再 delete 掉,就 ok 了,但是這里會有一個問題,如果傳遞進來的是值類型呢,值類型我們是不能給它添加屬性和方法的,所以 isThis.fn() 肯定會提示 isThis.fn is not a function,這里我們可以想一想值類型也是可以像對象一樣有屬性和方法的,并且可以添加屬性和方法,但是為什么賦值完后就找不到呢
這里要說下包裝類型了,值類型按理說是不可能有自己的屬性和方法的,但是考慮到有時候需要處理下雜七雜八的瑣事,所以當我們訪問或者賦值的時候,它會臨時給我們創(chuàng)建一個對應的包裝對象,在我們訪問或者賦值結束后那么這個包裝對象就會被清理掉,那么我們就可以這樣做,來模擬下包裝對象
var valueType = typeof isThis; if (valueType === "string") { isThis = new String(isThis) }else if (valueType === "number") { isThis = new Number(isThis) }else if (valueType === "boolean") { isThis = new Boolean(isThis) }else if (valueType === "symbol") { isThis = Object(isThis) }
恩,這樣一來就差不多了,接下來看看傳參,args 的元素才是我們想要的參數(shù),所以怎么拆開
var result = eval("isThis.fn(" + args.join() + ")");
使用 eval,得益于 eval 強大的能力,我們可以把字符串當做 js 代碼來執(zhí)行,并且可以得到返回值,完美
但是這里會有一個問題,如果參數(shù)是個對象,那么 eval 對參數(shù) toString 后我們我們就得不到想要的參數(shù)了,所以這里改造下,因為 eval 可以動態(tài)的改變作用域
var args = []; for (var i = 1, l = arguments.length; i< l; i++) { args.push("arguments[" + i + "]"); } var result = eval("isThis.fn(" + args.join() + ")");
這里我們用 args 存放著 arguments[1] arguments[1]... 這樣的字符串,那么 eval 執(zhí)行的時候會在上下文查找并綁定所需要的變量,這樣就可以實現(xiàn)參數(shù)傳遞了
完整代碼:
Function.prototype.callLike = function (isThis) { isThis = typeof isThis === "undefined" || isNull(isThis) ? window : isThis; var valueType = typeof isThis; if (valueType === "string") { isThis = new String(isThis) }else if (valueType === "number") { isThis = new Number(isThis) }else if (valueType === "boolean") { isThis = new Boolean(isThis) }else if (valueType === "symbol") { isThis = Object(isThis) } isThis.fn = this; var args = []; for (var i = 1, l = arguments.length; i< l; i++) { args.push("arguments[" + i + "]"); } var result = eval("isThis.fn(" + args.join() + ")"); delete isThis.fn; function isNull (value) { return typeof value === "object" && !value === true } return result; }
Function.prototype.applyLike = function (isThis, args) { isThis = typeof isThis === "undefined" || isNull(isThis) ? window : isThis; var valueType = typeof isThis; if (valueType === "string") { isThis = new String(isThis) }else if (valueType === "number") { isThis = new Number(isThis) }else if (valueType === "boolean") { isThis = new Boolean(isThis) }else if (valueType === "symbol") { isThis = Object(isThis) } isThis.fn = this; var args = []; for (var i = 1, l = arguments.length; i< l; i++) { args.push("arguments[" + i + "]"); } var result = eval("isThis.fn(" + args.join() + ")"); delete isThis.fn; function isNull (value) { return typeof value === "object" && !value === true } return result; }
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/89551.html
摘要:于是決定寫個歸納。如果懂了,那么下面的例子也就會做了已知調用函數(shù)的對象是,所以指向,即。相當于在全局作用域聲明了變量,并且賦值。實際上,調用函數(shù)的是關鍵字。使用來調用函數(shù),即函數(shù)的構造調用時,我們會構造一個新對象,并把它綁定到調用中的上。 對this的理解,我一直都是用一句話概括:誰調用它,它就指向誰。 好像也沒有什么問題,但仔細看了這本書和網(wǎng)上一些文章后,發(fā)現(xiàn)this的原理還挺講究的...
摘要:和概覽我們要將歸為一類,單獨歸為一類三者的共同點是都可以指定和都是綁定在的原型上的,所以的實例都可以調用這三個方法至于為什么,看完這篇文章你就懂了如果你不懂什么是實例的話,請移步深入淺出面向對象和原型概念篇深入淺出面向對象和原型概念篇第一個 1.call/apply和bind概覽 我們要將call/apply歸為一類,bind單獨歸為一類 三者的共同點是都可以指定this call/...
摘要:指向的改變構造函數(shù)中的操作符會調用函數(shù)的內部的方法,創(chuàng)建對象,之后調用函數(shù)的方法,把新創(chuàng)建對象作為值。調用函數(shù)時與設置的值以及箭頭函數(shù)皆為動態(tài)的改變指針的方法。這一特性使得箭頭函數(shù)在中的函數(shù)中使用起來很方便。 原文地址 JavaScript中的this 原理 錯誤的this指向 通常所說的:如果是全局環(huán)境中,this指向全局對象,如果是對象的方法,這this指向這個對象。 例子1: ...
摘要:半路出家的前端程序員應該不在少數(shù),我也是其中之一。年,馮馮同事兼師兄看我寫太費勁,跟我說對面樓在找,問我要不要學,說出來可能有點丟人,但是在那之前,我真得不知道什么是,什么是。 半路出家的前端程序員應該不在少數(shù),我也是其中之一。 為何會走向前端 非計算機專業(yè)的我,畢業(yè)之后,就職于一家電力行業(yè)公司,做過設備調試、部門助理、測試,也寫過一段時間的QT,那三年的時間,最難過的不是工作忙不忙,...
摘要:總結動態(tài)代理的相關原理已經(jīng)講解完畢,接下來讓我們回答以下幾個思考題。 【干貨點】 此處是【好好面試】系列文的第12篇文章。文章目標主要是通過原理剖析的方式解答Aop動態(tài)代理的面試熱點問題,通過一步步提出問題和了解原理的方式,我們可以記得更深更牢,進而解決被面試官卡住喉嚨的情況。問題如下 SpringBoot默認代理類型是什么 為什么不用靜態(tài)代理 JDK動態(tài)代理原理 CGLIB動態(tài)代理...
閱讀 3606·2021-11-22 11:59
閱讀 974·2021-09-27 13:36
閱讀 3635·2021-09-24 09:47
閱讀 2304·2021-09-01 11:39
閱讀 1002·2021-08-31 09:37
閱讀 2334·2021-08-05 10:01
閱讀 1714·2019-08-30 15:55
閱讀 724·2019-08-30 15:54