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