2019-12-01

  1. 樓盤(pán)表
    核心功能: 文件上傳,文件預(yù)覽,查看樓盤(pán)表數(shù)據(jù)
    我做的事情:面包屑公共組件開(kāi)發(fā),文件上傳公共組件開(kāi)發(fā)

項(xiàng)目難點(diǎn):

  1. 實(shí)現(xiàn)批量文件上傳,可配置化文件上傳組件

  2. 可點(diǎn)擊跳轉(zhuǎn)and刷新頁(yè)面的面包屑并且保留參數(shù),自定義路由關(guān)系自動(dòng)映射到面包屑

  3. 根據(jù)部署方式,調(diào)整打包方式

  4. 權(quán)限系統(tǒng)

  5. 面包屑

  6. 公共tabs組件
    面包屑和公共tabs組件與路由關(guān)聯(lián)

項(xiàng)目挑戰(zhàn),難度在于它是一個(gè)長(zhǎng)期的過(guò)程。

  1. 大量的類(lèi)似頁(yè)面,如何提高項(xiàng)目開(kāi)發(fā)效率,快速迭代,這些頁(yè)面分布在不同的系統(tǒng)中,封裝了大量頁(yè)面級(jí)別的業(yè)務(wù)組件。
    針對(duì)大量類(lèi)似頁(yè)面,我們需要做哪些事情

  2. 前期溝通
    產(chǎn)品,交互在不影響用戶(hù)體驗(yàn)的前提下,多個(gè)版本盡量保持一致
    設(shè)計(jì),設(shè)計(jì)會(huì)和前端形成一套設(shè)計(jì)規(guī)范,設(shè)計(jì)組件規(guī)范
    后端,接口一致性,多個(gè)項(xiàng)目迭代,接口數(shù)據(jù)結(jié)構(gòu)一致性,字段盡量一致
    前端,架構(gòu)搭建,組件和頁(yè)面組件的編寫(xiě)。

  3. tree

  4. 如何部署,靜態(tài)資源部署在cdn,html部署在weblogic

隨筆技術(shù)

  • seo
    服務(wù)端渲染
    直出,在服務(wù)器端獲取數(shù)據(jù)并渲染完成頁(yè)面后給到前端,用戶(hù)能夠直接看到頁(yè)面,這樣既解決了首屏問(wèn)題(服務(wù)器端獲取數(shù)據(jù)速度快)也解決了seo的問(wèn)題。

同構(gòu),瀏覽器端會(huì)在執(zhí)行一次,所以要進(jìn)行一次判斷,如果數(shù)據(jù)已經(jīng)獲取,那么就不要再獲取數(shù)據(jù)。

在當(dāng)前作用域之外執(zhí)行的函數(shù)就是閉包,定義時(shí)確定作用域,運(yùn)行時(shí)確定this,作用域鏈?zhǔn)腔谡{(diào)用棧的。

if (!Function.prototype.bind) {
  Function.prototype.bind = function(oThis) {
    if (typeof this !== 'function') {
        throw new TypeError('')
    }
  }
  let args = Array.prototype.slice.call(arguments, 1),
  fToBind = this, // this指向需要被綁定this的函數(shù)
  fNOP = function() {},
  fBound = function() {
    
  }
  
}

函數(shù)是對(duì)象的子類(lèi)型,可以像使用對(duì)象一樣使用函數(shù),new 出來(lái)的實(shí)例可以通過(guò)instance判斷是否是new 出來(lái)的實(shí)例

  • [[ Prototype ]]
    js的對(duì)象中有一個(gè)特殊的[[Prototype]]內(nèi)置屬性,其實(shí)就是對(duì)于其他對(duì)象的引用。當(dāng)你試圖引用對(duì)象屬性時(shí)會(huì)觸發(fā)[[GET]]操作,對(duì)于默認(rèn)的get來(lái)說(shuō),第一步是檢查對(duì)象本身是否有這個(gè)屬性,如果有就使用它。
    對(duì)于默認(rèn)的get操作來(lái)說(shuō),如果無(wú)法在對(duì)象本身找到需要的屬性,就會(huì)繼續(xù)訪(fǎng)問(wèn)protorype鏈,Object.create會(huì)創(chuàng)建一個(gè)對(duì)象并把這個(gè)對(duì)象的prototype關(guān)聯(lián)到指定的對(duì)象。當(dāng)使用各種語(yǔ)法進(jìn)行屬性查找時(shí)都會(huì)查找prototype鏈。
    給一個(gè)對(duì)象設(shè)置屬性不僅僅是添加一個(gè)新屬性或者修改已有屬性.
    不存在于自有對(duì)象,但是存在prototype中,會(huì)有三種情況
    如果在原型鏈上存在屬性,并且它是一個(gè)setter,那就一定會(huì)調(diào)用這個(gè)setter,屬性不會(huì)被添加到對(duì)象上。
  1. 如果在prototype鏈上層存在foo,但是他被標(biāo)記為只讀,那么無(wú)法修改已有屬性,或者創(chuàng)建屏蔽屬性。只讀會(huì)阻止鏈下層隱式創(chuàng)建同名屬性。這個(gè)限制只會(huì)存在于=賦值中,使用Object.defineProperty并不會(huì)受到影響。
    a++,首先通過(guò)原型查找到a,然后再對(duì)象自身的屬性上創(chuàng)建一個(gè)值,原型的值不會(huì)發(fā)生改變。
  • 類(lèi)
    原型繼承本質(zhì)是創(chuàng)建一個(gè)新的對(duì)象并且和原型建立關(guān)聯(lián)

  • 構(gòu)造函數(shù)
    Foo.prototype 默認(rèn)有一個(gè)公有并且不可枚舉的屬性constructor,這個(gè)屬性引用的是對(duì)象關(guān)聯(lián)的函數(shù)。new Foo 創(chuàng)建的對(duì)象也有一個(gè)constructor,指向創(chuàng)建這個(gè)對(duì)象的函數(shù)。
    實(shí)例上的constructor被委托到了原型的constructor,
    原型與原型之間可以通過(guò)object.create關(guān)聯(lián),也可以通過(guò)new關(guān)聯(lián)

  • 檢查類(lèi)的關(guān)系
    假設(shè)有對(duì)象a,如何尋找對(duì)象a委托的對(duì)象呢?檢查一個(gè)實(shí)例的繼承祖先通常被稱(chēng)為反射。
    instanceof 操作符的左側(cè)是一個(gè)普通對(duì)象,右操作數(shù)是一個(gè)函數(shù)。在左操作數(shù)的[[prototype]]中是否有指向右操作數(shù)的prototype的對(duì)象
    Foo.prototype.isPrototypeOf(a) 在a的整條proto中是否出現(xiàn)了Foo.prototype

  • 對(duì)象關(guān)聯(lián)
    如果在對(duì)象上沒(méi)有找到需要的屬性或者方法,引擎就會(huì)繼續(xù)在proto關(guān)聯(lián)的對(duì)象上查找。

  • 創(chuàng)建關(guān)聯(lián)
    使用Object.create不會(huì)生成prototype和constructor
    proxy是方法無(wú)法找到的行為

  • 比較思維模型

function Foo(who) {
  this.me = who
}
Foo.prototype.identify = function() {
  return 'i am' + this.me
}
function Bar(who) {
  Foo.call(this, who)
}
Bar.prototype = Object.create(Foo.prototype)
  • 事件循環(huán)
    js引擎并不是獨(dú)立運(yùn)行的,它運(yùn)行在宿主環(huán)境,對(duì)多數(shù)開(kāi)發(fā)者通常就是web瀏覽器。
    它們都提供了一種機(jī)制處理程序中多個(gè)塊的執(zhí)行,且執(zhí)行時(shí)調(diào)用js引擎,這種機(jī)制被稱(chēng)為事件循環(huán)。
    瀏覽器會(huì)偵聽(tīng)網(wǎng)絡(luò)的響應(yīng),拿到數(shù)據(jù)后,就會(huì)把回調(diào)函數(shù)插入到事件循環(huán)
    事件循環(huán)是一個(gè)用做隊(duì)列的數(shù)組,是一個(gè)持續(xù)運(yùn)行的循環(huán),循環(huán)的每一輪稱(chēng)為一個(gè)tick。對(duì)每個(gè)tick而言,如果隊(duì)列中存在等待事件,那么就會(huì)從隊(duì)列中摘下事件并執(zhí)行。這些事件就是你的回調(diào)函數(shù)。
    setTimeout并沒(méi)有把回調(diào)函數(shù)掛在事件循環(huán)隊(duì)列中。它所做的是設(shè)定一個(gè)定時(shí)器,定時(shí)器到時(shí)后,環(huán)境會(huì)把你的回調(diào)函數(shù)放在事件循環(huán)中,這樣在未來(lái)某個(gè)時(shí)刻的tick會(huì)摘下并執(zhí)行這個(gè)回調(diào)。

  • 并行和線(xiàn)程
    事件循環(huán)把自身的工作分成一個(gè)個(gè)任務(wù)并順序執(zhí)行,不允許對(duì)共享內(nèi)存的訪(fǎng)問(wèn)和修改。通過(guò)分立線(xiàn)程中彼此合作的事件循環(huán),并行和順序執(zhí)行可以共存。
    js一次只能處理一個(gè)事件

  • 任務(wù)
    有一個(gè)新的概念建立在事件循環(huán)隊(duì)列之上,叫做任務(wù)隊(duì)列,它是掛在事件循環(huán)隊(duì)列的每個(gè)tick之后的一個(gè)隊(duì)列。可能出現(xiàn)的異步動(dòng)作不會(huì)導(dǎo)致一個(gè)完整的新事件添加到事件循環(huán)隊(duì)列當(dāng)中,而會(huì)在當(dāng)前tick的任務(wù)隊(duì)列末尾添加一個(gè)任務(wù)。
    事件循環(huán)類(lèi)似于有一個(gè)活動(dòng)免費(fèi)領(lǐng)禮物,你領(lǐng)完禮物之后需要排隊(duì)才能再領(lǐng)。而任務(wù)隊(duì)列類(lèi)似于領(lǐng)了之后,插隊(duì)繼續(xù)領(lǐng)禮物。
    一個(gè)任務(wù)可能引起更多任務(wù)被添加到同一個(gè)隊(duì)列末尾,所以,理論上說(shuō),job event可能無(wú)限循環(huán)。任務(wù)處理是在當(dāng)前tick循環(huán)結(jié)尾處。
    一旦有事件需要運(yùn)行,事件循環(huán)就會(huì)運(yùn)行,直到隊(duì)列清空。事件循環(huán)的每一輪稱(chēng)為一個(gè)tick。用戶(hù)交互、IO和定時(shí)器會(huì)向事件隊(duì)列中加入事件。
    不管then回調(diào)返回的是什么,都會(huì)被自動(dòng)設(shè)置為promise的完成。

  • 元編程
    元編程是對(duì)程序編程的編程
    舉例來(lái)說(shuō),如果想要查看對(duì)象a和另一個(gè)對(duì)象b的關(guān)系是否是prototype鏈接的。用for in循環(huán)枚舉對(duì)象的鍵,或者檢查對(duì)象是否是某個(gè)類(lèi)構(gòu)造器的實(shí)例。
    元編程關(guān)注以下幾點(diǎn):代碼查看自身,代碼修改自身,代碼修改默認(rèn)語(yǔ)言特性,以此影響其他代碼。
    元編程的目標(biāo)是利用語(yǔ)言自身的內(nèi)省能力使代碼的其余部分更具描述性、表達(dá)性和靈活性。如果函數(shù)設(shè)定了name值,那么這個(gè)值通常就是開(kāi)發(fā)者工具中棧蹤跡使用的名稱(chēng)。你的代碼在某些情況下可能想要了解自身,想要知道某個(gè)函數(shù)的名稱(chēng)是什么。

  • 元屬性

  • 代理
    代理是一種由你創(chuàng)建的特殊的對(duì)象,它封裝了另一個(gè)普通對(duì)象,或者說(shuō)擋在這個(gè)普通對(duì)象前面。你可以在代理對(duì)象上注冊(cè)特殊的處理函數(shù),代理上執(zhí)行各種操作時(shí)會(huì)調(diào)用這個(gè)程序。
    你可以在代理上定義的trap處理函數(shù)的一個(gè)例子是get,當(dāng)你試圖訪(fǎng)問(wèn)對(duì)象屬性的時(shí)候,它攔截get運(yùn)算。
    在跟蹤console.log之后,我們把對(duì)obj的操作通過(guò)reflect.get轉(zhuǎn)發(fā)。每個(gè)可用的代理trap都有一個(gè)對(duì)應(yīng)的同名Reflect函數(shù)即可。
    這里的映射是有意對(duì)稱(chēng)的。每個(gè)代理處理函數(shù)在對(duì)應(yīng)的元編程任務(wù)執(zhí)行的時(shí)候進(jìn)行攔截.
    我們把對(duì)obj的操作通過(guò)Reflect.get()轉(zhuǎn)發(fā)。每個(gè)代理處理函數(shù)都有一個(gè)自動(dòng)調(diào)用相應(yīng)的Reflect工具的默認(rèn)定義。

  • 代理局限性
    可以在對(duì)象上執(zhí)行的很廣泛的一組基本操作都可以通過(guò)這些元編程處理函數(shù)trap。但有一些操作是無(wú)法攔截的。

  • 可取消代理

  • 使用代理
    通過(guò)元編程的proxy,我們可以攔截對(duì)對(duì)象處理的幾乎所有行為。

  1. 代理在先,代理在后
    我們通??梢园汛砜醋魇菍?duì)目標(biāo)對(duì)象的包裝。代理成為了代碼交互的主要對(duì)象,而實(shí)際的目標(biāo)對(duì)象保持被保護(hù)的狀態(tài)。
  • 代理hack[[ prototype ]]鏈
    [[ prototype ]]機(jī)制主要是通過(guò)[[ Get ]]運(yùn)算,當(dāng)直接對(duì)象沒(méi)有屬性時(shí),get會(huì)把這個(gè)運(yùn)算交給[[ prototype ]]。

  • Reflect對(duì)象就是一個(gè)平凡對(duì)象
    它持有對(duì)應(yīng)于各種可控的元編程任務(wù)的靜態(tài)函數(shù)。這些函數(shù)一對(duì)一對(duì)應(yīng)著代理可以定義的處理函數(shù)方法。
    Reflect和Object的對(duì)應(yīng)工具行為方式類(lèi)似。但是,如果第一個(gè)參數(shù)不是對(duì)象,Object會(huì)試圖把它轉(zhuǎn)換成對(duì)象。而Reflect則會(huì)拋出一個(gè)錯(cuò)誤。
    Reflect的元編程能力提供了模擬各種語(yǔ)法特性的編程等價(jià)事物,把之前隱藏的抽象操作暴露出來(lái)。比如,可以利用這些能力擴(kuò)展功能和API,以實(shí)現(xiàn)領(lǐng)域特定語(yǔ)言(DSL)。

  • 屬性排序
    對(duì)于es6,擁有屬性的列出順序由算法定義,可以順序只對(duì)特斯你給的ownKeys等方法有保證
    其順序?yàn)椋?/p>

  1. 首先,按照數(shù)字上升排序,枚舉所有整數(shù)索引擁有的屬性;
  2. 然后,按照創(chuàng)建順序枚舉其余的擁有的字符串屬性名;
  3. 最后,按照創(chuàng)建順序枚舉擁有的符號(hào)屬性;
  • 尾遞歸調(diào)用
    通常,在一個(gè)函數(shù)內(nèi)部調(diào)用另一個(gè)函數(shù)的時(shí)候,會(huì)分配第二個(gè)棧zhen來(lái)獨(dú)立管理第二個(gè)函數(shù)調(diào)用的變量/狀態(tài)。這個(gè)分配不但消耗處理時(shí)間,也消耗額外內(nèi)存。
    當(dāng)進(jìn)行遞歸編程時(shí),調(diào)用棧的深度很容易達(dá)到成百上千,甚至更多。如果內(nèi)存的使用無(wú)限制增長(zhǎng),將會(huì)導(dǎo)致問(wèn)題。
    有一種稱(chēng)為尾調(diào)用的函數(shù)調(diào)用模式,可以以避免額外棧幀分配的方式進(jìn)行優(yōu)化。如果可以避免額外的分配,就沒(méi)有理由任意限制調(diào)用棧的深度。
    尾調(diào)用是一個(gè)return函數(shù)調(diào)用的語(yǔ)句,除了調(diào)用后返回其返回值之外沒(méi)有任何其他動(dòng)作。通過(guò)這種方式不需要分配額外的棧幀。引擎不需要對(duì)下一個(gè)函數(shù)調(diào)用創(chuàng)建一個(gè)新的棧幀。這能夠工作是因?yàn)橐粋€(gè)函數(shù)不需要保留任何當(dāng)前狀態(tài)。

  • 非tco優(yōu)化
    把每個(gè)部分的結(jié)果用一個(gè)函數(shù)表示,這些函數(shù)或者返回另外一個(gè)部分結(jié)果函數(shù),或者返回最終結(jié)果。然后只需要循環(huán)直到得到的結(jié)果不是函數(shù),得到的就是最終結(jié)果。

function trampoline(res) {
  while(typeof res == 'function') {
    res = res()
  }
  return res
}

let foo = (() => {
  function _foo(acc, x) {
    if (x <= 1) return acc;
    return () => {
      return _foo((x/2)+acc, x-1)
    }
  }
  return (x) => {
    return trampoline(_foo(1, x))
  }
})()

這個(gè)重寫(xiě)需要最小的改動(dòng)把遞歸轉(zhuǎn)化為trampoline中的循環(huán)。

  1. 首先,把 return _foo .. 一行封裝在·partial表達(dá)式中
  2. 然后,把_foo調(diào)用封裝在trampoline中
function foo(x) {
  let acc = 1;
  while(x>1) {
    acc = (x/2)+acc
    x--
  }
  return acc
}
  • 元在何處
    可以在運(yùn)行時(shí)判斷引擎支持哪些特性。其中就包括TCO,盡管方法十分暴力
try {
  (function foo(x) {
    if (x < 5E5) return foo(x+1)
  })(1)
}
catch (err) {
  
}

在非TCO引擎中,遞歸循環(huán)最終會(huì)失敗,拋出一個(gè)異常被捕獲。
所以我們可以通過(guò)這種特性測(cè)試來(lái)決定是加載使用遞歸的應(yīng)用代碼版本,還是轉(zhuǎn)換為不需要遞歸的版本。

自適應(yīng)代碼

function foo(x) {
  function _foo() {
    if (x > 1) {
      acc = acc + (x/2);
      x--
      return _foo()
    }
  }
  var acc=1;
  while(x>1) {
    try {_foo()} catch(err){}  
  }
  return acc
}
foo(123456)

這個(gè)算法盡可能多的使用了遞歸,但是是通過(guò)作用域內(nèi)的變量x和acc保持進(jìn)展?fàn)顟B(tài)。如果整個(gè)問(wèn)題都可以不出錯(cuò)的通過(guò)遞歸解決,那么很好。如果引擎在某處殺死了遞歸,我們就會(huì)在catch中捕獲到,然后再試一次,繼續(xù)我們其余的工作。
這種形式可以看做一種元編程,理由是在運(yùn)行時(shí)探索引擎的能力來(lái)遞歸地完成任務(wù),并可能為引擎局限提供替代版本。

  • 小結(jié)
    元編程是指把程序的邏輯轉(zhuǎn)向關(guān)注自身,要么是為了查看自己的結(jié)構(gòu),要么是為了修改它。元編程的主要價(jià)值是擴(kuò)展語(yǔ)言的一般機(jī)制來(lái)提供額外的新功能。
    從匿名函數(shù)到函數(shù)名推導(dǎo),到提供了構(gòu)造器調(diào)用方式這樣的信息的元屬性,你可以比過(guò)去更深入查看程序運(yùn)行時(shí)的結(jié)構(gòu)。通過(guò)公開(kāi)符號(hào)可以覆蓋原本特性,代理可以攔截并自定義對(duì)象的各種底層操作,Reflect提供了工具來(lái)模擬它們。

  • 異步函數(shù)
    async function 本質(zhì)上就是生成器+promise+run模式的語(yǔ)法糖
    async function有一個(gè)沒(méi)有解決的問(wèn)題,因?yàn)樗环祷匾粋€(gè)promise,所以沒(méi)有辦法從外部取消一個(gè)正在運(yùn)行的async function實(shí)例。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 概要 64學(xué)時(shí) 3.5學(xué)分 章節(jié)安排 電子商務(wù)網(wǎng)站概況 HTML5+CSS3 JavaScript Node 電子...
    阿啊阿吖丁閱讀 9,853評(píng)論 0 3
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類(lèi)型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,667評(píng)論 1 32
  • 第3章 基本概念 3.1 語(yǔ)法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類(lèi)型 5種簡(jiǎn)單數(shù)據(jù)類(lèi)型:Unde...
    RickCole閱讀 5,527評(píng)論 0 21
  • JS內(nèi)置對(duì)象之Date時(shí)間對(duì)象 Date對(duì)象是ECMAScript標(biāo)準(zhǔn)定義的,瀏覽器內(nèi)置 函數(shù)對(duì)象之一。 一、簡(jiǎn)看...
    果又是甲嘛底訥閱讀 379評(píng)論 0 0
  • 特別說(shuō)明,為便于查閱,文章轉(zhuǎn)自https://github.com/getify/You-Dont-Know-JS...
    殺破狼real閱讀 544評(píng)論 0 1

友情鏈接更多精彩內(nèi)容