亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

從規(guī)范去看Function.prototype.apply到底是怎么工作的?

tanglijun / 1790人閱讀

摘要:如果是或者,會將作為值。否則,被調(diào)用的函數(shù),進行轉(zhuǎn)換后,作為值。又怎么操作這個很神奇。能轉(zhuǎn)換它的參數(shù)為到總共個整數(shù)中的一個,這個函數(shù)遵循以下規(guī)則。不斷加入新方法的規(guī)范也是這個初衷。

今天看element-react源碼的時候,又看到了這張似曾相識卻又異常陌生的老面孔,那就是Function.prototype.apply()...

import React from "react";
import PropTypes from "prop-types";
import classnames from "classnames";

export default class Component extends React.Component {
  classNames(...args) {
         return classnames(args);
  }

  className(...args) {
         return this.classNames.apply(this, args.concat([this.props.className]));
  }

  style(args) {
         return Object.assign({}, args, this.props.style)
  }
}

Component.propTypes = {
  className: PropTypes.string,
  style: PropTypes.object
};

雖然高設(shè),犀牛書以及你不知道的Javascrit都看過apply的原理,但依然沒什么卵用,可能是缺少實踐的原因,看完就忘。

Q:
其中這句this.classNames.apply(this, args.concat([this.props.className])),又把我搞得暈頭轉(zhuǎn)向,this到底是誰?沒猜錯的話應(yīng)該是組件實例吧?
那為啥不直接 this.classNames(args.concat([this.props.className])),直接傳一個數(shù)組不就行了嗎?
為什么一定要用this.classNames.apply(this, args.concat([this.props.className]))?
同理,印象中apply用來取數(shù)組最大最小值很方便,Math.max.apply(null,[1,3,8,2]),但是Math.apply( [1,3,8,2] )卻返回傳參類型錯誤?這又是為什么?

帶著這些問題,我又一次開始了啃規(guī)范之旅。

Function.prototype.apply (thisArg, argArray)
The apply method takes two arguments, thisArg and argArray, and performs a function call using the [[Call]] property of the object. If the object does not have a [[Call]] property, a TypeError exception is thrown. If thisArg is null or undefined, the called function is passed the global object as the this value. Otherwise, the called function is passed ToObject(thisArg) as the this value. If argArray is null or undefined, the called function is passed no arguments. Otherwise, if argArray is neither an array nor an arguments object (see 10.1.8), a TypeError exception is thrown. If argArray is either an array or an arguments object, the function is passed the (ToUint32(argArray.length)) arguments argArray[0], argArray[1], …, argArray[ToUint32(argArray.length)–1].

apply有2個方法,一個是thisArg,一個是argArray,然后再執(zhí)行對象的[[call]]屬性。如果對象沒有call屬性,一個TypeError會被扔出來。
如果thisArg是null或者undefined,會將global作為this值。否則,被調(diào)用的函數(shù),進行ToObject(thisArg)轉(zhuǎn)換后,作為this值。
如果argArray是null或者undefined,被調(diào)用函數(shù)不傳入任何參數(shù)。否則,argArray如果既不是數(shù)組也不是arguments object(類數(shù)組對象),會報錯TypeError.
如果 argArray是數(shù)組或者類數(shù)組對象,被調(diào)用函數(shù)傳入ToUnit32(argArray.length) arguments argArray[0],argArray[1]一直到argArray[ToUint32(argArray.length)–1].

ToObject內(nèi)部怎么操作?這個不用管。
ToUnit32又怎么操作?這個很神奇。

ToUint32: (Unsigned 32 Bit Integer)
The operator ToUint32 converts its argument to one of 232 integer values in the range 0 through 232?1,
inclusive. This operator functions as follows:

Call ToNumber on the input argument.

If Result(1) is NaN, +0, ?0, +∞, or ?∞, return +0.

Compute sign(Result(1)) * floor(abs(Result(1))).

Compute Result(3) modulo 232; that is, a finite integer value k of Number type with positive sign and

less than 232 in magnitude such the mathematical difference of Result(3) and k is mathematically an
integer multiple of 232.

Return Result(4).

ToUnit32能轉(zhuǎn)換它的參數(shù)為0到231總共232個整數(shù)中的一個,這個函數(shù)遵循以下規(guī)則。
1.對輸入?yún)?shù)調(diào)用ToNumber()函數(shù)
2.如果Result(1)是 NaN, +0, ?0, +∞, 或者 ?∞, return +0
3.計算sign(Result(1)*floor(abs(Result(1))))
4.計算Result(3) modulo 232;就是說 一個無窮的正整數(shù)值k,大于0小于232,Result(3)與k的數(shù)學(xué)差異是232的整數(shù)倍。
5.返回Result(4)

A1:
多說無益,舉個例子實在:
Math.max.apply(null,[1,3,2,""])

第一步:global值替換null,瀏覽器環(huán)境為window
Math.max.apply(window,[1,3,2,""])

第二步:[1,3,2,""].length傳入到ToUnit32()中
ToUnit32(4)

第三步:計算ToUnit32(4), 作為數(shù)組轉(zhuǎn)換成arguments類數(shù)組對象的編號
1.ToNumber(4)→Result(1)=4
2.Not pass the condition
3.Math.sign(4*Math.floor(Math.abs(4))) →Result(3)=1
4.1 Mod 232 → Result(4) =1
5.return 1

第四步:傳入arguments到Math.max中
第三步會生成(1)arguments 類數(shù)組對象(是否為純函數(shù)方式生成暫時未知),將這個arguments傳入到Math.max中,與直接這樣寫Math.max(1,3,2,"")的效果一樣,此時就會返回最大值3。

這里有一個很重要的坑,為什么arguments傳入,也可以像正常Math.max(1,3,2,"")一樣?
其實這個坑是因為Math.max(1,3,2,"")這個例子中的實參,在函數(shù)內(nèi)部的實參就是arguments,且這個arguments的長度為4,這和絕大多數(shù)的函數(shù)一樣,除箭頭函數(shù)外的所有函數(shù),都有這個arguemnts實參array-like object。

看完這個, Math.max.apply(null,[1,3,8,2])的內(nèi)部原理應(yīng)該也就清楚了吧。

A2:
回到源代碼中this.classNames.apply(this, args.concat([this.props.className]))
1.為什么直接傳入["foo","bar"]數(shù)組不行?
因為當(dāng)我們傳入["foo","bar"]到classNames時,此時return classnames(args);中的args會變成一個二維數(shù)組[["foo","bar"]],與classnames模塊的預(yù)期值類型一維數(shù)組相悖。
2.為什么調(diào)用Function.prototype.apply后就可以?
因為如規(guī)范中的第三步中所示, this.classNames.apply(this, args.concat([this.props.className]))中,在apply的內(nèi)部算法中,會將args.concat([this.props.className])這個數(shù)組,轉(zhuǎn)換為一個實參類數(shù)組對象arguments,跳過形參賦值步驟,直接深入到 this.classNames()內(nèi)部,這樣一來,就實現(xiàn)了一個一個傳值的效果,其中的...args就會成為一個一個獨立的參數(shù),而args會作為實參數(shù)組傳給classnames函數(shù)。

說了這么多,總結(jié)起來其實就一句話:

callObject.method.apply(thisArg,thisArray),可以將thisArray轉(zhuǎn)化為arguments,傳入到callObject.method內(nèi)部。

加粗加斜的這句真的很重要!
加粗加斜的這句真的很重要!
加粗加斜的這句真的很重要!

參考:
1.The mathematical function sign(x) yields 1 if x is positive and ?1 if x is negative. The sign function is not
used in this standard for cases when x is zero
2.求模
對于整數(shù)a,b來說,取模運算或者求余運算的方法要分如下兩步:
1.求整數(shù)商:c=a/b
2.計算?;蛘哂鄶?shù):r=a-(c*b)
求模運算和求余運算在第一步不同
取余運算在計算商值向正無窮方向舍棄小數(shù)位
取模運算在計算商值向負無窮方向舍棄小數(shù)位
例如:4/(-3)約等于-1.3
在取余運算時候商值向0方向舍棄小數(shù)位為-1
在取模運算時商值向負無窮方向舍棄小數(shù)位為-2
所以
4rem(-3)=1
4mod(-3)=-2
3.C和JS中%表示取余,python中表示取模
python中%表示取模,have a try 1 Mod 232 →1

Merry Christmas ~
That"s it !

2019.8.20更新

js忍者秘籍給出的精簡解釋是:“js可以通過apply和call顯示指定任意對象作為其函數(shù)上下文?!睆娏医ㄗh閱讀P52~P55。言簡意賅,通俗易懂。

主要有兩個用途:

普通函數(shù)中指定函數(shù)上下文

回調(diào)函數(shù)中強制指定函數(shù)上下文

回調(diào)函數(shù)強制指定函數(shù)上下文很好地體現(xiàn)了函數(shù)式編程的思想,創(chuàng)建一個函數(shù)接收每個元素,并且對每個元素做處理。

本質(zhì)上,apply和call都是為了增強代碼的可擴展性,提升編程的效率。

我想這也是js中每一個方法或者api的初衷,提供更加便利的操作,解放初更多的生產(chǎn)力。不斷加入新方法的es規(guī)范也是這個初衷。

由于我使用vue比較多,所以根據(jù)以上的應(yīng)用場景出1個單文件組件示例和1個普通示例供參考:

// 普通函數(shù)中指定函數(shù)上下文
// 通過Math.max()獲得數(shù)組中的最大項
// 回調(diào)函數(shù)中強制指定函數(shù)上下文
// 手動實現(xiàn)一個Array.prototype.filter
const numbers = [1, 2, 3, 4];
function arrayFilter(array, callback) {
  const result = [];
  for (let i = 0; i < array.length; i++) {
    const validate = callback.call(array[i], array[i]);
    if (validate) {
      result.push(array[i]);
    }
  }
  return result;
}

const evenArrays = arrayFilter(numbers, (n) => n % 2 === 0);
console.log(evenArrays);// [2, 4]

期待和大家交流,共同進步,歡迎大家加入我創(chuàng)建的與前端開發(fā)密切相關(guān)的技術(shù)討論小組:

SegmentFault專欄:趁你還年輕,做個優(yōu)秀的前端工程師

Github博客: 趁你還年輕233的個人博客

掘金主頁:趁你還年輕233

SegmentFault技術(shù)圈: ES新規(guī)范語法糖

知乎專欄:趁你還年輕,做個優(yōu)秀的前端工程師

前端開發(fā)交流群:660634678

努力成為優(yōu)秀前端工程師!

加油,前端同學(xué)們!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/90394.html

相關(guān)文章

  • 規(guī)范去看Function.prototype.call到底怎么工作?

    摘要:抽象操作是在調(diào)用函數(shù)對象的內(nèi)部的方法。指的是調(diào)用函數(shù),指的是的值,然后是傳入到內(nèi)部方法相應(yīng)參數(shù)的值。切換上下文執(zhí)行,為函數(shù)調(diào)用棧在尾部調(diào)用函數(shù)做準備,切換運行中執(zhí)行上下文,實現(xiàn)上下文的動態(tài)改變。萬事具備,執(zhí)行,調(diào)用函數(shù)即可。 showImg(https://segmentfault.com/img/bVbwBui?w=657&h=382); 今天在學(xué)習(xí)前端工程化的過程中,遇到一個是實驗...

    DandJ 評論0 收藏0
  • 【2】this

    摘要:否則如果是或,則設(shè)綁定為全局對象。令為解釋執(zhí)行的結(jié)果。返回一個值類型的引用,其基值為且其引用名為,嚴格模式標記為。進入函數(shù)代碼,為,非嚴格模式下將賦值為全局對象。內(nèi)置函數(shù)如何使用的內(nèi)置函數(shù)修改是通過給的內(nèi)置方法傳遞來實現(xiàn)的。 this 說到this,需要明確三方面內(nèi)容: this何時被賦值 this被賦了什么值 內(nèi)置函數(shù)如何使用this的 this何時被賦值 進入函數(shù)代碼 當(dāng)控制流...

    Alex 評論0 收藏0
  • 深入call apply bind

    摘要:眾所周知,這三個函數(shù)都是改變執(zhí)行上下文的,那么我們來捋一捋,這些函數(shù)內(nèi)部到底做了什么。 前言 稍微翻了一下call,apply, bind 的各種論壇上的文章, 發(fā)現(xiàn)講的都太淺了,大部分都只講了個用法, 對于實現(xiàn)的原理卻都沒有提,因此,在這里,我寫下這篇文章, 希望能讓大家認識到原理所在。 眾所周知, 這三個函數(shù)都是改變執(zhí)行上下文的 , 那么我們來捋一捋,這些函數(shù)內(nèi)部到底做了什么。 c...

    Alex 評論0 收藏0
  • javascript中Function、ArrowFunction和GeneratorFunctio

    摘要:等價與注意如果構(gòu)造函數(shù)有自己的返回,那么情況有所不同。,定義了的屬性,默認是聲明的函數(shù)名,匿名函數(shù)是。匿名函數(shù)表達式和函數(shù)聲明都不會創(chuàng)建匿名作用域。 ECMAScript規(guī)范中對Function的文檔描述,我認為是ECMAScript規(guī)范中最復(fù)雜也是最不好理解的一部分,它涉及到了各方面。光對Function就分了Function Definitions、Arrow Function D...

    cyixlq 評論0 收藏0
  • 看完這篇文章還不會call/apply/bind來找我。

    摘要:關(guān)于的指向的問題請參照我的學(xué)習(xí)筆記。那么在這里事實上都改變了函數(shù)方法被調(diào)用時的指向。那么回調(diào)函數(shù)在執(zhí)行的時候指向還是。大家看完之后應(yīng)該已經(jīng)懂了把還是不懂的話在評論區(qū)留言,我給大家解答。 先從一個小題目開始吧: 要實現(xiàn)一個加法函數(shù),這個時候向函數(shù)當(dāng)中傳遞個數(shù)大于0的若干個整形數(shù)據(jù),求所有這些數(shù)據(jù)的和。 Function.prototype.call Function.prototype...

    Java3y 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<