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