Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 在线视频免费国产成人,亚洲一区二区免费,99久久精品免费看国产

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          如何衡量一個(gè)人的 JavaScript 水平?

          如何衡量一個(gè)人的 JavaScript 水平?

          源:魚頭的Web海洋

          前言

          之前刷某乎的時(shí)候,看到這么一個(gè)問題:“如何衡量一個(gè)人的 JavaScript 水平?[2]”然后自己也不要臉地回答了一下這個(gè)問題。以下是我的答案:

          原文如下:

          A:看一個(gè)人寫代碼是否有規(guī)范,代碼是否壯健,是否可拓展,可讀性高不高,API設(shè)計(jì)是否合理。

          這些都是長(zhǎng)年累月積累下來的且獨(dú)立于編程語(yǔ)言以外的。

          遠(yuǎn)比把什么手寫bind,原型鏈,閉包給背下來更有價(jià)值。

          這才是證明你代碼水平的關(guān)鍵點(diǎn)。

          Q:在面試的時(shí)候如何快速判斷出呢?

          A:讓面試者設(shè)計(jì)個(gè)組件,不用寫,回答就行。從API設(shè)計(jì),文檔編寫,項(xiàng)目結(jié)構(gòu),單元測(cè)試,編寫模式,性能優(yōu)化等方面來回答。

          有工作經(jīng)驗(yàn)的人,基本業(yè)務(wù)邏輯都能寫,但是寫的好不好,就是經(jīng)驗(yàn)跟能力以及學(xué)習(xí)力的體現(xiàn) 。

          個(gè)人說明

          首先來個(gè)免責(zé)聲明,以上的回答都是個(gè)人的經(jīng)驗(yàn)與見解,答案肯定不唯一,甚至不一定全對(duì),所以求輕噴。

          上面問如何在面試的時(shí)候快速判斷對(duì)方是否是高級(jí)前端的時(shí)候,我為什么說是“設(shè)計(jì)組件”呢?

          因?yàn)槲矣X得有一定實(shí)力的前端來說,“組件”這個(gè)概念是繞不過的,或者看過開源組件的源碼,或者自己寫過組件。

          對(duì)于一般的業(yè)務(wù)問題,我相信作為一個(gè)從業(yè)了一定時(shí)間的開發(fā)者,無論水平如何,這都不是問題,但是如何區(qū)分這個(gè)開發(fā)者的水平,可以通過他寫的代碼來判斷,當(dāng)然也不完全是,畢竟在996或者趕進(jìn)度的時(shí)候,很容易就會(huì)為了完成快速出產(chǎn)品而寫,這種情況下代碼質(zhì)量跟個(gè)人水平不一定能體現(xiàn)。

          下面,我們以設(shè)計(jì)一個(gè)“按鈕(<Button>)組件”為例,來探索這個(gè)問題。

          首先“按鈕(<Button>)”的作用這個(gè)我們是否明確?它是裝飾性的組件還是功能性的組件?

          這個(gè)問題很簡(jiǎn)單,“按鈕(<Button>)”是一個(gè)功能性的組件,是讓用戶通過點(diǎn)擊或觸碰來采取行動(dòng)并做出選擇的一個(gè)組件。

          場(chǎng)景

          那么“按鈕(<Button>)”通常放在什么地方?有經(jīng)驗(yàn)的開發(fā)可能會(huì)想到以下場(chǎng)景:

          ?對(duì)話框?模態(tài)窗口?表單?卡片?工具欄

          代表狀態(tài)可能會(huì)有以下幾種:

          ?默認(rèn)狀態(tài)?初始狀態(tài)?信息狀態(tài)?警告狀態(tài)?危險(xiǎn)狀態(tài)

          形態(tài)可能會(huì)有以下幾種:

          ?實(shí)心按鈕?文本按鈕?描邊按鈕?圖標(biāo)按鈕?圓角按鈕?直角按鈕

          尺寸可能會(huì)有以下幾種:

          ?small?medium?large

          操作性可能會(huì)有以下幾種:

          ?回車鍵點(diǎn)擊?鼠標(biāo)點(diǎn)擊?觸摸點(diǎn)擊?禁止點(diǎn)擊

          攜帶的事件可能有以下兩種:

          ?click事件?回車鍵keydown事件?tap事件

          以上雖然是偏樣式,但是作為一個(gè)組件開發(fā)者,這都是我們?nèi)粘K枰紤]的。

          API

          在API的設(shè)計(jì)環(huán)節(jié),我們通過上述的場(chǎng)景,我們可能會(huì)暴露出以下的API

          ?type:按鈕狀態(tài)?size:按鈕尺寸?color:按鈕顏色?text:按鈕內(nèi)的文本?icon:按鈕內(nèi)的圖標(biāo)?htmlType:原生按鈕支持的type屬性?attrs:其他的原生屬性?variant:按鈕形態(tài)?click:鼠標(biāo)點(diǎn)擊事件?tap:觸摸屏點(diǎn)擊事件?keydown:回車鍵按下事件

          編寫核心邏輯

          在我們API設(shè)計(jì)好之后,我們就可以開始開發(fā)了,這時(shí)候根據(jù)我們項(xiàng)目的類型,選擇的開發(fā)工具以及模式,可能會(huì)有所不同。

          我們是獨(dú)立編寫還是直接在項(xiàng)目里面去編寫,如果是獨(dú)立編寫,選擇哪個(gè)打包工具,是gulp還是webpack還是其它,為什么這么選?

          例如如果我們是用TS寫,我們可能需要編寫B(tài)utton.d.ts,如果是vue的組件,我們還得考慮Vue.use注入到Vue中,也就是Button.install(vue),如果是react,我們還得考慮是否使用React.forwardRef來進(jìn)行ref轉(zhuǎn)發(fā)。

          然后就是我們的代碼規(guī)范,是用Function還是Class,共同的代碼塊如何抽象,如何,還有命名規(guī)范是什么,哪些屬性必選,哪些屬性可選,默認(rèn)值是什么?我們是怎么考慮的?

          所以最終的組件使用可能會(huì)是這種形式:




          import Button from './componenet/Button'<Button htmlType="submit" aria-label="add" variant="contained" color="rgba(17, 82, 147, 1)" click="clickHandler" />添加</Button>

          單元測(cè)試

          在我們開發(fā)的過程中,有一道麻煩但又必不可少的工序就是單元測(cè)試,這時(shí)候單元測(cè)試的庫(kù)我們是怎么選?用Jest還是Mocha?測(cè)試用例怎么寫?如何模擬點(diǎn)擊或者異步響應(yīng)?是否需要快照(snapshots)?這也是在我們的考慮范圍內(nèi)。

          所以我們的測(cè)試腳本可能長(zhǎng)這樣:












          import Button from './componenet/Button'import { shallow } from 'enzyme'describe('<Button />', ()=> {  it('render success', ()=> {    const wrapper=shallow((      <Button htmlType="submit" aria-label="add" variant="contained" color="rgba(17, 82, 147, 1)" click="clickHandler" />添加</Button>    ))    expect(wrapper.text('添加')).to.equal(true)  })})

          其它

          其它的諸如開發(fā)文檔,使用文檔,版本迭代,項(xiàng)目配置,打包開發(fā)優(yōu)化,以及其他自動(dòng)化的功能,也是我們所需要考慮。

          總結(jié)

          以上便是我們?cè)陂_發(fā)一個(gè)“按鈕(<Button>)組件”時(shí)可能會(huì)考慮到的點(diǎn),可能有不夠完善的地方,但是我想說的意思是,這其實(shí)可以很好的衡量一個(gè)人的JavaScript水平。比如你再會(huì)手寫原型鏈關(guān)系圖,閉包,防抖,節(jié)流等基礎(chǔ)概念,但是如果不在項(xiàng)目中運(yùn)用起來,終究是紙上談兵,對(duì)技術(shù)水平?jīng)]有太多實(shí)質(zhì)的幫助,當(dāng)然不是說精通這些內(nèi)容不好,但是比起實(shí)戰(zhàn),還是差強(qiáng)人意。

          能手寫代碼的不一定是高級(jí),但是如果能寫好一個(gè)組件,水平再差也不會(huì)差到哪里去。

          本文似乎有點(diǎn)文不對(duì)題了,本來談的是“如何衡量一個(gè)人的JavaScript水平”,結(jié)果卻超綱了許多。但是通過這種方式,確實(shí)能夠判斷出一個(gè)人代碼水平,當(dāng)然也并不只是JS,換成安卓,IOS也同樣適用。

          不知道你是通過什么方式來衡量一個(gè)的JavaScript水平的呢?歡迎留言區(qū)域回復(fù)互動(dòng)。

          者|顏海鏡

          編輯|覃云

          出處丨前端之巔

          本文已獲作者授權(quán),轉(zhuǎn)載來源:

          https://segmentfault.com/a/1190000016389031

          劃重點(diǎn),這是一道面試必考題,很多面試官都喜歡問這個(gè)問題,我就被問過好幾次了。



          要實(shí)現(xiàn)上圖的效果看似很簡(jiǎn)單,實(shí)則暗藏玄機(jī),本文總結(jié)了一下 CSS 實(shí)現(xiàn)水平垂直居中的方式大概有下面這些,本文將逐一介紹一下,我將本文整理成了一個(gè) github 倉(cāng)庫(kù)在:https://github.com/yanhaijing/vertical-center

          歡迎大家 star。

          僅居中元素定寬高適用:

          • absolute + 負(fù) margin
          • absolute + margin auto
          • absolute + calc

          居中元素不定寬高:

          • absolute + transform
          • lineheight
          • writing-mode
          • table
          • css-table
          • flex
          • grid

          1.absolute + 負(fù) margin

          為了實(shí)現(xiàn)上面的效果先來做些準(zhǔn)備工作,假設(shè) HTML 代碼如下,總共兩個(gè)元素,父元素和子元素:

          <div class="wp">
           <div class="box size">123123</div>
          </div>
          

          wp 是父元素的類名,box 是子元素的類名,因?yàn)橛卸▽捄筒欢▽挼膮^(qū)別,size 用來表示指定寬度,下面是所有效果都要用到的公共代碼,主要是設(shè)置顏色和寬高。

          注意:后面不在重復(fù)這段公共代碼,只會(huì)給出相應(yīng)提示。

          /* 公共代碼 */
          .wp {
           border: 1px solid red;
           width: 300px;
           height: 300px;
          }
          .box {
           background: green; 
          }
          .box.size{
           width: 100px;
           height: 100px;
          }
          /* 公共代碼 */
          

          絕對(duì)定位的百分比是相對(duì)于父元素的寬高,通過這個(gè)特性可以讓子元素的居中顯示,但絕對(duì)定位是基于子元素的左上角,期望的效果是子元素的中心居中顯示。

          為了修正這個(gè)問題,可以借助外邊距的負(fù)值,負(fù)的外邊距可以讓元素向相反方向定位,通過指定子元素的外邊距為子元素寬度一半的負(fù)值,就可以讓子元素居中了,css 代碼如下。

          /* 此處引用上面的公共代碼 */
          /* 此處引用上面的公共代碼 */
          /* 定位代碼 */
          .wp {
           position: relative;
          }
          .box {
           position: absolute;;
           top: 50%;
           left: 50%;
           margin-left: -50px;
           margin-top: -50px;
          }
          

          這是我比較常用的方式,這種方式比較好理解,兼容性也很好,缺點(diǎn)是需要知道子元素的寬高。

          點(diǎn)擊查看完整 DEMO:

          http://yanhaijing.com/vertical-center/absolute1.html

          2.absolute + margin auto

          這種方式也要求居中元素的寬高必須固定,HTML 代碼如下:

          <div class="wp">
           <div class="box size">123123</div>
          </div>
          

          這種方式通過設(shè)置各個(gè)方向的距離都是 0,此時(shí)再講 margin 設(shè)為 auto,就可以在各個(gè)方向上居中了。

          /* 此處引用上面的公共代碼 */
          /* 此處引用上面的公共代碼 */
          /* 定位代碼 */
          .wp {
           position: relative;
          }
          .box {
           position: absolute;;
           top: 0;
           left: 0;
           right: 0;
           bottom: 0;
           margin: auto;
          }
          

          這種方法兼容性也很好,缺點(diǎn)是需要知道子元素的寬高。

          點(diǎn)擊查看完整 DEMO:

          http://yanhaijing.com/vertical-center/absolute2.html

          3.absolute + calc

          這種方式也要求居中元素的寬高必須固定,所以我們?yōu)?box 增加 size 類,HTML 代碼如下:

          <div class="wp">
           <div class="box size">123123</div>
          </div>
          

          感謝 css3 帶來了計(jì)算屬性,既然 top 的百分比是基于元素的左上角,那么在減去寬度的一半就好了,代碼如下

          /* 此處引用上面的公共代碼 */
          /* 此處引用上面的公共代碼 */
          /* 定位代碼 */
          .wp {
           position: relative;
          }
          .box {
           position: absolute;;
           top: calc(50% - 50px);
           left: calc(50% - 50px);
          }
          

          這種方法兼容性依賴 calc 的兼容性,缺點(diǎn)是需要知道子元素的寬高。

          點(diǎn)擊查看完整 DEMO:

          http://yanhaijing.com/vertical-center/absolute3.html

          4.absolute + transform

          還是絕對(duì)定位,但這個(gè)方法不需要子元素固定寬高,所以不再需要 size 類了,HTML 代碼如下:

          <div class="wp">
           <div class="box">123123</div>
          </div>
          

          修復(fù)絕對(duì)定位的問題,還可以使用 css3 新增的 transform,transform 的 translate 屬性也可以設(shè)置百分比,其是相對(duì)于自身的寬和高,所以可以講 translate 設(shè)置為 -50%,就可以做到居中了,代碼如下:

          /* 此處引用上面的公共代碼 */
          /* 此處引用上面的公共代碼 */
          /* 定位代碼 */
          .wp {
           position: relative;
          }
          .box {
           position: absolute;
           top: 50%;
           left: 50%;
           transform: translate(-50%, -50%);
          }
          

          這種方法兼容性依賴 translate2d 的兼容性。

          點(diǎn)擊查看完整 DEMO:

          http://yanhaijing.com/vertical-center/absolute4.html

          5.lineheight

          利用行內(nèi)元素居中屬性也可以做到水平垂直居中,HTML 代碼如下:

          <div class="wp">
           <div class="box">123123</div>
          </div>
          

          把 box 設(shè)置為行內(nèi)元素,通過 text-align 就可以做到水平居中,但很多同學(xué)可能不知道通過通過 vertical-align 也可以在垂直方向做到居中,代碼如下:

          /* 此處引用上面的公共代碼 */
          /* 此處引用上面的公共代碼 */
          /* 定位代碼 */
          .wp {
           line-height: 300px;
           text-align: center;
           font-size: 0px;
          }
          .box {
           font-size: 16px;
           display: inline-block;
           vertical-align: middle;
           line-height: initial;
           text-align: left; /* 修正文字 */
          }
          

          這種方法需要在子元素中將文字顯示重置為想要的效果。

          點(diǎn)擊查看完整 DEMO:

          http://yanhaijing.com/vertical-center/lineheight.html

          6.writing-mode

          很多同學(xué)一定和我一樣不知道 writing-mode 屬性,感謝 @張?chǎng)涡窭蠋煹姆答仯?jiǎn)單來說 writing-mode 可以改變文字的顯示方向,比如可以通過 writing-mode 讓文字的顯示變?yōu)榇怪狈较颉?/p>

          <div class="div1">水平方向</div>
          <div class="div2">垂直方向</div>
          .div2 {
           writing-mode: vertical-lr;
          }
          

          顯示效果如下:

          水平方向
          垂
          直
          方
          向
          

          更神奇的是所有水平方向上的 css 屬性,都會(huì)變?yōu)榇怪狈较蛏系膶傩裕热?text-align,通過 writing-mode 和 text-align 就可以做到水平和垂直方向的居中了,只不過要稍微麻煩一點(diǎn):

          <div class="wp">
           <div class="wp-inner">
           <div class="box">123123</div>
           </div>
          </div>
          /* 此處引用上面的公共代碼 */
          /* 此處引用上面的公共代碼 */
          /* 定位代碼 */
          .wp {
           writing-mode: vertical-lr;
           text-align: center;
          }
          .wp-inner {
           writing-mode: horizontal-tb;
           display: inline-block;
           text-align: center;
           width: 100%;
          }
          .box {
           display: inline-block;
           margin: auto;
           text-align: left;
          }
          

          這種方法實(shí)現(xiàn)起來和理解起來都稍微有些復(fù)雜。

          點(diǎn)擊查看完整 DEMO:

          http://yanhaijing.com/vertical-center/writing-mode.html

          7.table

          曾經(jīng) table 被用來做頁(yè)面布局,現(xiàn)在沒人這么做了,但 table 也能夠?qū)崿F(xiàn)水平垂直居中,但是會(huì)增加很多冗余代碼:

          <table>
           <tbody>
           <tr>
           <td class="wp">
           <div class="box">123123</div>
           </td>
           </tr>
           </tbody>
          </table>
          

          tabel 單元格中的內(nèi)容天然就是垂直居中的,只要添加一個(gè)水平居中屬性就好了。

          .wp {
           text-align: center;
          }
          .box {
           display: inline-block;
          }
          

          這種方法就是代碼太冗余,而且也不是 table 的正確用法。

          點(diǎn)擊查看完整 DEMO:

          http://yanhaijing.com/vertical-center/table.html

          8.css-table

          css 新增的 table 屬性,可以讓我們把普通元素,變?yōu)?table 元素的現(xiàn)實(shí)效果,通過這個(gè)特性也可以實(shí)現(xiàn)水平垂直居中。

          <div class="wp">
           <div class="box">123123</div>
          </div>
          

          下面通過 css 屬性,可以讓 div 顯示的和 table 一樣:

          .wp {
           display: table-cell;
           text-align: center;
           vertical-align: middle;
          }
          .box {
           display: inline-block;
          }
          

          這種方法和 table 一樣的原理,但卻沒有那么多冗余代碼,兼容性也還不錯(cuò)。

          點(diǎn)擊查看完整 DEMO:

          http://yanhaijing.com/vertical-center/css-table.html

          9.flex

          flex 作為現(xiàn)代的布局方案,顛覆了過去的經(jīng)驗(yàn),只需幾行代碼就可以優(yōu)雅的做到水平垂直居中。

          <div class="wp">
           <div class="box">123123</div>
          </div>
          .wp {
           display: flex;
           justify-content: center;
           align-items: center;
          }
          

          目前在移動(dòng)端已經(jīng)完全可以使用 flex 了,PC 端需要看自己業(yè)務(wù)的兼容性情況。

          點(diǎn)擊查看完整 DEMO:

          http://yanhaijing.com/vertical-center/flex.html

          10.grid

          感謝 @一絲姐 反饋的這個(gè)方案,css 新出的網(wǎng)格布局,由于兼容性不太好,一直沒太關(guān)注,通過 grid 也可以實(shí)現(xiàn)水平垂直居中。

          <div class="wp">
           <div class="box">123123</div>
          </div>
          .wp {
           display: grid;
          }
          .box {
           align-self: center;
           justify-self: center;
          }
          

          代碼量也很少,但兼容性不如 flex,不推薦使用。

          點(diǎn)擊查看完整 DEMO:

          http://yanhaijing.com/vertical-center/grid.html

          總結(jié)

          下面對(duì)比下各個(gè)方式的優(yōu)缺點(diǎn),肯定又雙叒叕該有同學(xué)說回字的寫法了,簡(jiǎn)單總結(jié)下:

          • PC 端有兼容性要求,寬高固定,推薦 absolute + 負(fù) margin
          • PC 端有兼容要求,寬高不固定,推薦 css-table
          • PC 端無兼容性要求,推薦 flex
          • 移動(dòng)端推薦使用 flex

          小貼士:關(guān)于 flex 的兼容性決方案,請(qǐng)看這里:

          https://yanhaijing.com/css/2016/08/21/flex-practice-on-mobile/


          最近發(fā)現(xiàn)很多同學(xué)都對(duì) css 不夠重視,這其實(shí)是不正確的,比如下面的這么簡(jiǎn)單的問題都有那么多同學(xué)不會(huì),我也是很無語(yǔ):

          <div class="red blue">123</div>
          <div class="blue red">123</div>
          .red {
           color: red
          }
          .blue {
           color: blue
          }
          

          問兩個(gè) div 的顏色分別是什么,竟然只有 40% 的同學(xué)能夠答對(duì),這 40% 中還有很多同學(xué)不知道為什么,希望這些同學(xué)好好補(bǔ)習(xí)下 CSS 基礎(chǔ)。

          備JavaScript面試時(shí)應(yīng)了解的事項(xiàng)。

          JavaScript現(xiàn)在是一種非常流行的編程語(yǔ)言,基于該語(yǔ)言,派生了大量庫(kù)和框架。 但是,無論高層生態(tài)系統(tǒng)如何發(fā)展,離不開原始的JavaScript。 在這里,我選擇了4個(gè)JavaScript面試問題來測(cè)試程序員使用普通JavaScript的技能。

          1.實(shí)現(xiàn)Array.prototype.map

          如何手動(dòng)實(shí)現(xiàn)Array.prototype.map方法?

          熟練使用數(shù)組的內(nèi)置方法并不難。但是,如果您只是熟悉語(yǔ)法而又不了解原理,那么很難真正理解JavaScript。

          對(duì)于Array.prototype.map,它將創(chuàng)建一個(gè)新數(shù)組,其中將填充在調(diào)用數(shù)組中每個(gè)元素上調(diào)用提供的函數(shù)的結(jié)果。

          如果引用lodash,我們可以編寫一個(gè)map函數(shù),如下所示:

          function map(array, iteratee) { 
            let index=-1 
            const length=array==null ? 0 : array.length 
            const result=new Array(length) 
            while (++index < length) { 
              result[index]=iteratee(array[index], index, array) 
            } 
            return result
          }

          使用示例:

          2. Object.defineProperty和代理

          如何實(shí)現(xiàn)這種編碼效果?

          我們可以看到,當(dāng)我們嘗試連續(xù)打印obj.a三次時(shí),會(huì)得到三種不同的結(jié)果。看起來多么不可思議!

          您可以創(chuàng)建一個(gè)神秘的對(duì)象obj來實(shí)現(xiàn)此效果嗎?

          實(shí)際上,此問題有三種解決方案:

          · 訪問者屬性

          · Object.defineProperty

          · 代理

          根據(jù)ECMAScript,對(duì)象的屬性可以采用兩種形式:

          從邏輯上講,對(duì)象是屬性的集合。每個(gè)屬性都是數(shù)據(jù)屬性或訪問器屬性:

          · 數(shù)據(jù)屬性將鍵值與ECMAScript語(yǔ)言值和一組布爾屬性相關(guān)聯(lián)。

          · 訪問器屬性將鍵值與一個(gè)或兩個(gè)訪問器函數(shù)以及一組布爾屬性相關(guān)聯(lián)。訪問器函數(shù)用于存儲(chǔ)或檢索與屬性關(guān)聯(lián)的ECMAScript語(yǔ)言值。

          所謂的數(shù)據(jù)屬性通常是我們寫的:

          let obj={ a: 1, b: 2}

          我們對(duì)一個(gè)對(duì)象的屬性只有兩個(gè)操作:讀取屬性和設(shè)置屬性。對(duì)于訪問器屬性,我們使用get和set方法定義屬性,其編寫方式如下:

          let obj={ 
            get a(){ 
              console.log('triggle get a() method') 
              console.log('you can do anything as you want') 
              return 1 
            }, 
            set a(value){ 
              console.log('triggle set a() method') 
              console.log('you can do anything as you want') 
              console.log(`you are trying to assign ${value} to obj.a`) 
            }
          }

          訪問屬性為我們提供了強(qiáng)大的元編程能力,因此我們可以通過以下方式滿足我們的要求:

          let obj={ 
            _initValue: 0, 
            get a() { 
              this._initValue++; 
              return this._initValue 
            }
          }
          
          console.log(obj.a, obj.a, obj.a)

          第二種方法是使用Object.defineProperty,該方法的工作方式與我們用來訪問屬性的方法相同,除了不是直接聲明訪問屬性,而是通過Object.defineProperty配置訪問屬性。

          這使用起來更加靈活,因此我們可以這樣編寫:

          let obj={}Object.defineProperty(obj, 'a', { get: (function(){ let initValue=0; return function(){ initValue++; return initValue } })()})console.log(obj.a, obj.a, obj.a)

          在這里的get方法中,我們使用了一個(gè)閉包,以便我們需要使用的變量initValue隱藏在閉包中,并且不會(huì)污染其他范圍。

          第三種方法是使用代理。

          使用代理,我們可以攔截對(duì)對(duì)象屬性的訪問。 只要我們使用代理來攔截對(duì)obj.a的訪問,然后依次返回1、2和3,我們就可以在以下條件之前完成要求:

          let initValue=0;
          let obj=new Proxy({}, { 
            get: function(item, property, itemProxy){ 
              if(property==='a'){ 
                initValue++; 
                return initValue 
              } 
              return item[property] 
            }
          })
          
          console.log(obj.a, obj.a, obj.a)

          為什么理解這個(gè)問題很重要?因?yàn)镺bject.defineProperty和Proxy給了我們強(qiáng)大的元編程能力,所以我們可以適當(dāng)?shù)匦薷膶?duì)象以做一些特殊的事情。

          在著名的前端框架Vue中,其核心機(jī)制之一是數(shù)據(jù)的雙向綁定。在Vue2.0中,Vue通過使用Object.defineProperty實(shí)現(xiàn)了該機(jī)制。在Vue3.0中,使用Proxy完成此機(jī)制。

          如果不掌握Vue之類的框架,您將無法真正理解。如果您掌握了這些原則,則只需學(xué)習(xí)Vue的一半,就可以獲得兩倍的結(jié)果。

          3.范圍和閉包

          運(yùn)行此代碼的結(jié)果是什么?

          function foo(a,b) { 
            console.log(b) 
            return { 
              foo:function(c){ 
                return foo(c,a); 
              } 
            };
          }
          
          let res=foo(0); 
          res.foo(1); 
          res.foo(2); 
          res.foo(3);

          上面的代碼同時(shí)具有多個(gè)嵌套函數(shù)和三個(gè)foo嵌套函數(shù),乍一看看起來非常繁瑣。那么,我們?nèi)绾卫斫膺@一點(diǎn)呢?

          首先,請(qǐng)確保上面的代碼中有多少個(gè)功能?我們可以看到在上面的代碼中的兩個(gè)地方都使用了關(guān)鍵字函數(shù),因此上面的代碼中有兩個(gè)函數(shù),即第一行函數(shù)foo(a,b) 和第四行 foo:function(c)。并且這兩個(gè)函數(shù)具有相同的名稱。

          第二個(gè)問題:第5行的foo(c,a)調(diào)用哪個(gè)函數(shù)?如果不確定,讓我們來看一個(gè)簡(jiǎn)單的示例:

          var obj={ 
            fn:function (){ 
              console.log(fn); 
            }
          };
          
          obj.fn()

          如果我們運(yùn)行該代碼,是否會(huì)引發(fā)異常? 答案是肯定的。

          這是因?yàn)閛bj.fn()方法的上限是全局的,并且無法訪問obj內(nèi)部的fn方法。

          回到前面的示例,以同樣的邏輯,當(dāng)我們調(diào)用foo(c,a)時(shí),實(shí)際上是在第一行上調(diào)用foo函數(shù)。

          當(dāng)我們調(diào)用res.foo(1)時(shí),將調(diào)用哪個(gè)foo? 顯然,第4行的foo函數(shù)被調(diào)用。

          因?yàn)檫@兩個(gè)foo函數(shù)的工作方式不同,所以我們可以將其中一個(gè)的名稱更改為bar,以使我們更容易理解代碼。

          function foo(a,b) { 
            console.log(b) 
            return { 
              bar:function(c){ 
                return foo(c,a); 
              } 
            };
          }
          
          let res=foo(0); 
          res.bar(1); 
          res.bar(2); 
          res.bar(3);

          此更改不會(huì)影響最終結(jié)果,但會(huì)使我們更容易理解代碼。如果將來遇到類似的問題,請(qǐng)嘗試此技巧。

          每次調(diào)用一個(gè)函數(shù)時(shí),都會(huì)創(chuàng)建一個(gè)新的作用域,因此我們可以繪制圖表以幫助我們理解代碼工作原理的邏輯。

          當(dāng)我們執(zhí)行l(wèi)et res=foo(0);時(shí),實(shí)際上是在執(zhí)行foo(0,undefiend)。此時(shí),將在程序中創(chuàng)建一個(gè)新的作用域,在當(dāng)前作用域中a=0,b=undefined。因此,我繪制的圖看起來像這樣。

          然后將執(zhí)行console.log(b),因此它第一次在控制臺(tái)中打印出" undefined"。

          然后執(zhí)行res.bar(1),創(chuàng)建一個(gè)新范圍,其中c=1:

          然后從上面的函數(shù)中再次調(diào)用foo(c,a),它實(shí)際上是foo(1,0),作用域如下所示:

          在新作用域中,a的值為1,b的值為0,因此控制臺(tái)將打印出0。

          再次執(zhí)行res.bar(2)。注意,res.bar(2)和res.bar(1)是并行關(guān)系,因此我們應(yīng)該像這樣繪制范圍圖:

          因此,在此代碼中,控制臺(tái)也會(huì)打印出值0。

          執(zhí)行res.bar(3)的過程也是如此,控制臺(tái)仍顯示0。

          因此,以上代碼的最終結(jié)果是:

          實(shí)際上,上述問題可以用其他方式改變。例如,可以將其更改為以下內(nèi)容:

          function foo(a,b) { 
            console.log(b) 
            return { 
              foo:function(c){ 
                return foo(c,a); 
              } 
            };
          }
          
          foo(0).foo(1).foo(2).foo(3);

          在解決這個(gè)問題之前,我們要做的第一件事是區(qū)分兩個(gè)不同的foo函數(shù),因此可以將上面的代碼更改為如下所示:

          function foo(a,b) { 
            console.log(b) 
            return { 
              bar:function(c){ 
                return foo(c,a); 
              } 
            };
          }
          
           foo(0).bar(1).bar(2).bar(3);

          執(zhí)行foo(0)時(shí),作用域與以前相同,然后控制臺(tái)將打印出" undefined"。

          然后執(zhí)行.bar(1)創(chuàng)建一個(gè)新的作用域。此參數(shù)1實(shí)際上是c的值。

          然后.bar(1)方法再次調(diào)用foo(c,a),它實(shí)際上是foo(1,0)。這里的參數(shù)1實(shí)際上將是新作用域中a的值,而0將是新作用域中b的值。

          因此,控制臺(tái)隨后輸出了b的值,即0。

          再次調(diào)用.bar(2),在新作用域中c的值為2:

          然后.bar(2)調(diào)用foo(c,a),它實(shí)際上是foo(2,1),其中2是新作用域中a的值,而1是新作用域中b的值。

          因此,控制臺(tái)隨后輸出了b的值,即0。

          然后它將執(zhí)行.bar(3),該過程與之前相同,因此我將不擴(kuò)展其描述,此步驟控制臺(tái)將打印出2。

          如上所述,代碼運(yùn)行的最終結(jié)果是:

          好了,經(jīng)過漫長(zhǎng)的旅程,我們終于得到了答案。 這個(gè)問題很好地檢驗(yàn)了受訪者對(duì)封閉和范圍的理解。

          4.撰寫 Compose

          假設(shè)我們有一個(gè)看起來像這樣的函數(shù):

          function compose (middleware) { // some code}

          compose函數(shù)接受函數(shù)數(shù)組中間件:

          let middleware=[]
          middleware.push((next)=> { 
            console.log(1) 
            next() 
            console.log(1.1)
          })
          
          middleware.push((next)=> { 
            console.log(2) 
            next() 
            console.log(2.1)
          })
          
          middleware.push(()=> { 
            console.log(3)
          })
          
          let fn=compose(middleware)
          
          fn()

          當(dāng)我們嘗試執(zhí)行fn時(shí),它將調(diào)用中間件中的函數(shù),并將下一個(gè)函數(shù)作為參數(shù)傳遞給每個(gè)小函數(shù)。

          如果我們?cè)谝粋€(gè)小函數(shù)中執(zhí)行next,則將調(diào)用中間件中該函數(shù)的next函數(shù)。而且,如果您接下來不執(zhí)行,程序也不會(huì)崩潰。

          執(zhí)行完上面的代碼后,我們得到以下結(jié)果:

          1232.11.1

          那么,我們?nèi)绾尉帉懸粋€(gè)compose函數(shù)來做到這一點(diǎn)呢?

          首先,compose函數(shù)必須返回一個(gè)composed函數(shù),因此我們可以編寫如下代碼:

          function compose (middleware) { 
            return function () { }
          }

          然后,在返回的函數(shù)中,中間件的第一個(gè)函數(shù)開始執(zhí)行。我們還將傳遞下一個(gè)函數(shù)作為其參數(shù)。所以讓我們這樣寫:

          function compose (middleware) { 
            return function () { 
              let f1=middleware[0] 
              f1(function next(){ }) 
            }
          }

          下一個(gè)功能充當(dāng)繼續(xù)在中間件中運(yùn)行的開關(guān),如下所示:

          function compose (middleware) { 
            return function () { 
              let f1=middleware[0] 
              f1(function next(){ 
                let f2=middleware[1] 
                f2(function next(){ ... }) 
              }) 
            }
          }

          然后繼續(xù)在下一個(gè)函數(shù)中調(diào)用第三個(gè)函數(shù)…等待,這看起來像遞歸! 因此,我們可以編寫一個(gè)遞歸函數(shù)來完成此嵌套調(diào)用:

          function compose (middleware) { 
            return function () { 
              dispatch(0) 
              function dispatch (i) { 
                const fn=middleware[i] 
                if (!fn) return null 
                fn(function next () { 
                  dispatch(i + 1) 
                }) 
              } 
            }
          }

          好的,這就是我們的撰寫功能,所以讓我們對(duì)其進(jìn)行測(cè)試:

          好吧,此功能完全可以完成其所需的工作。 但是我們也可以優(yōu)化我們的compose函數(shù)可以支持異步函數(shù)。 我們可以改進(jìn)以下代碼:

          function compose (middleware) { 
            return async function () { 
              await dispatch(0) 
              function async dispatch (i) { 
                const fn=middleware[i] 
                if (!fn) 
                  return null 
                await fn(function next () { 
                  dispatch(i + 1) 
                }) 
              } 
            }
          }

          實(shí)際上,以上的撰寫功能是眾所周知的節(jié)點(diǎn)框架koa的核心機(jī)制。

          當(dāng)我選擇候選人時(shí),我接受他/她對(duì)某些框架不熟悉。畢竟,JavaScript生態(tài)系統(tǒng)中有太多的庫(kù)和框架,沒有人能完全掌握它們。但是我確實(shí)希望候選人知道這些重要的原始JavaScript技巧,因?yàn)樗鼈兪撬袔?kù)和框架的基礎(chǔ)。

          結(jié)論

          實(shí)際上,我的草稿中還有其他一些面試問題,但由于本文篇幅有限,因此在此不再繼續(xù)解釋。稍后再與您分享。

          本文主要涉及普通JavaScript,而不涉及瀏覽器,節(jié)點(diǎn),框架,算法,設(shè)計(jì)模式等。如果您對(duì)這些主題也感興趣,請(qǐng)隨時(shí)發(fā)表評(píng)論。

          感謝您的閱讀!

          (本文由聞數(shù)起舞翻譯自bitfish的文章《Improve Your JavaScript Level With These 4 Questions》,轉(zhuǎn)載請(qǐng)注明出處,原文鏈接:https://medium.com/javascript-in-plain-english/i-use-these-4-questions-to-find-outstanding-javascript-developers-4a468ea17155)


          主站蜘蛛池模板: 色狠狠色噜噜Av天堂一区| 国产日韩一区二区三区| 久久精品一区二区三区中文字幕 | 精品无码国产一区二区三区51安| 中文字幕AV一区二区三区人妻少妇| 无码毛片一区二区三区中文字幕 | 亚洲国产一区在线观看| 精品国产一区二区三区2021| 无码少妇丰满熟妇一区二区| 久久一本一区二区三区| 国产成人高清视频一区二区| 无码中文人妻在线一区| 久久久综合亚洲色一区二区三区 | 国产A∨国片精品一区二区| 色婷婷香蕉在线一区二区| 亚洲一区二区三区夜色| 久久精品国产一区二区三区肥胖| 无码AV一区二区三区无码 | 精品国产免费观看一区| 亚洲日韩一区二区三区| 亚洲国产精品一区二区久| 亚洲AV美女一区二区三区| 精品福利一区二区三| 亚洲国产一区二区三区青草影视| 一区二区三区国产| 老熟妇仑乱视频一区二区| 乱子伦一区二区三区| 日本一区二区三区久久| 亚洲人成网站18禁止一区| 人妻免费一区二区三区最新| 亚洲国产精品自在线一区二区| 麻豆一区二区免费播放网站| 精品一区二区久久久久久久网精| 国产高清视频一区二区| 在线精品国产一区二区三区| 亚洲香蕉久久一区二区三区四区| 国产成人精品一区二区A片带套| 国产在线一区二区三区av| 中文字幕在线看视频一区二区三区| 亚洲AV无码一区二区一二区| 无码精品人妻一区二区三区影院|