[JavaScript與Web程序設計]筆記

  • 幻燈片的關鍵點需要完全看懂,把幾個點混在一個題里面
  • 死記硬背的成分不太多,點比較小,文字長串
  • 填空的一些形式:給出程序,通過console.log()填空;
    問答有一題送分,要規整排版好,寫上兩三個點就差不多了;
    編程題會拿一些幻燈片的程序,看懂之后能重寫;

劃重點

運行js ,值和類型,typeof(null)==object, 未被賦值的變量也是undefined,聲明數值中前后的0可以忽略,整數判斷,NaN不和自己等,字符串,模板字符串,轉義符,嵌入表達式,==obj混合考察==,delete操作符-權限,['key'],訪問不存在的屬性-undefined-用什么方式判斷,內置類,不加new,==數組混合==,==數組那幾個方法如slice==,‘use strict'不用管,先有雞,==變量作用域==,property帶記憶函數,函數參數數目,==rest參數,隱式參數==,bind,走神了漏了很多函數的沒看,global.this,==箭頭函數==,==運行上下文==,閉包說不用管,==詞法環境==題目多,obj的方法們,遍歷器很復雜,for ofspreadforEach,常識性方法們reduce,==屬性描述符==,類型轉換那一堆不用記但要理解,string->number(+),轉換那些會有題目,|| &&, ==, ===,五六講考不到,==頁面事件處理==,HTML和CSS看明白了就行,==定時器==,==事件傳播,處理,代理監聽==,==異步==分值多,setTimeout 讀文件 仿真怎么做 ==Generator==原理是函數運行上下文,==Promise對象==catch

基本語法與特性

  • 一個變量同時只能引用一個值,一個值可同時被多個變量引用

  • 一個==值只能具有一個類型==且不可改變,一個類型至少具有一個值

    const :不改變變量和值之間的引用關系,原子類型的值不被改變,因此效果和常引用一致

  • js中的值有七種類型

    所有原子類型的值在聲明后都不會發生變化

    • null

      let a = null // 'undefined'
      typeof a // 'object' 這是一個原生bug

    • undefined

      • 只有一個值undefined,聲明變量沒被賦值時被缺省賦值為undefined; 對未聲明變量的引用會得到錯誤,但是typeof是可以的(let不行)
    • boolean

      • 假 - N0fun : NaN, +0, -0, false, undefined,null,""(空字符串)
    • number

      • 控制小數位數toFixed(),控制有效數字個數toPrecision()

      • 數值相等判斷用=== (Number.EPS=2^-52)

      • NaN也是number,不和任何值相等,它是唯一不和自己相等的值
        當然復合類型判斷相等是看地址,所以{}!=={},[]!==[],function(){}!==function(){}

      • -1/0 === -Infinity

      • 2^ 969和1.79E308都還可以,多了就不大行了 ——數值范圍不用記

      • 還有Object的方法is(a,b)編碼相等,isInteger(),isSafeInteger()其實就是2^53-1含以下

        function is(v1,v2) { /*自己寫判斷相等函數*/
            if (v1 === 0 && v2 === 0) return 1/v1 === 1/v2 //+-0
            if (v1 !== v1) return v2 !== v2                //NaN
            return v1 === v2
        }
        
    • string

      • ES采用UTF-16的編碼方式將string中的16位整數序列翻譯成字符

      模板字符串前后要用括起來,可以嵌入表達式 以下顯示為s='Hi,3+4=7'let a = 3, b = 4;let s='Hi,${a}+${b}=${a+b}';`

    • symbol:提供了一種存儲無關的方式來表達一個符號

      • 初始動機是為obj加入private property,而在實際使用中,這作為定制/擴展系統功能的一種方式

      • 創建/使用:

        let mySymbol = Symbol("a description")       //不準用new
        let myObject = {}
        myObject[mySymbol] = "a property with a symbol key"
        let mySymoblObj = Object(mySymbol)  //用函數封裝到obj里面
        let mySymbol1 = Symbol(), mySymbol2 = Symbol()
        mySymbol1 === mySymbol2               //false 永遠不相同
        
        • 共享Symbol類型的值:利用全局的symbol值注冊庫
          let mySymbol = Symbol.for("description")
      • 在for-in語句中,不會遍歷到obj里symbol類型的key

    • object(non-primitive type)

      • property(key~string/symbol,value,...)
        在沒增加權限控制時,可以逐步添加屬性
        點操作符只能存取key不會導致歧義的屬性,而方括號都可以

          /*ES6 simplified object literal declaration*/
        let name = "shellywhen", age = 20
        let good$Girl = {name,age}
          /*former object literal declaration*/
        let normal_Girl = {name: "shellywhen", age: 20}
          /*use a inner constructor*/
        let girl = new Object()           //"new" is neccessary
        girl.name = "shellywhen"
        girl.age = 20    
        
      • built-in obj
        這和自動裝箱(automatic-boxing)有關,讓原子類型具有方法
        ES規定,對Number/Boolean/String不加new就是強制類型轉換
        超出Array長度的賦值可能出現空洞(hole),可以修改length階段
      • objects are truthy,如new Boolean(false) == true
  • 傳值/傳引用?

    根據ES規范中的文字描述,賦值語句/函數調用傳的都是==引用==。

  • 一些build in object

    • Array

      • 建立:myList = ["dog", false, NaN]
        myList=new Array("dog",false,NaN)

        new Array 參數只有一個整數時,理解為整個數組長度為該值
        為避免邊界行為,使用Array.of()來傳入數組內容

      • 首末刪改:push pop unshift shift (看字母數)
        中段刪改:splice(start, deleteCount, ...item)
        取中段:slice(start = 0, end = length-1)

    • Function 既是constructor也是 b-i-o

      • let foo = new Function("a","b","return a+b")
      • typeof 一個 function obj 返回"function"
  • Prototype

    1. 每個obj相關聯且僅關聯一個Prototype
    2. Prototype要么是obj要么是null值

    ES規范規定,Prototype是obj的一種internal state,被存放在名為[[Prototype]]的internal slot中;

    對于一個obj,包含properties, internal slots, internal methods
    <img src="pic/ObjectComponent.png" style="zoom:30%"></img>

    obj之間通過prototype關系形成原型鏈,提升obj的動態性

    • 設置
      創建時關聯:let obj = Object.create(proto)
      創建后關聯:Object.setPrototypeOf(obj, proto)
      獲得一個obj的prototype:let proto = Object.getPrototypeOf(obj)
  • 特性

    主函數可被理解為global object的一個property

    無論在程序的什么位置,只要對未聲明變量賦值,改賦值語句一旦執行后該變量自動變為global object的一個property

    在源文件第一行寫下"use strict"就能消滅js的常見邪惡特性

    js在運行前,通常有一個耗時幾微秒的編譯活動,變量的作用域在這個編譯活動中形成。js更接近一種解釋型語言。從效果來看,編譯把作用域的變量聲明提到前面。==考點區:var奇怪行為==

    • 使用function declaration聲明的函數變量具有函數級(體)的作用域
    • 使用let const聲明的變量具有塊級的作用域(從聲明處開始)

Function

function是特殊類型的object,對object做的事情對function也能做——可以賦值給變量,放到數組中,作為property的value,<u>作為參數(callback function),作為返回值</u>,為function添加property

ES6為function添加了name這個property

數組的sort方法接收一個函數,該函數接收兩個值,返回二者相對位置

數組的forEach方法接受一個回調函數,該函數負責對每個元素逐個處理

let isPrime.store = isPrime.store || {}      //使用或運算符設置默認值
  • 函數參數

    • 調用函數時傳遞的參數數量不需要等于定義時參數的數量

    • 傳入一個數組,直接在數組前加...(叫做spread操作符)

    • 參數默認值(ES6引入) let add = (a = 0, b = 0) => a+b

      let add = (a = 0, b = 1) => a+b
      console.log(add(b=2))                                  // 2
      
  • 當缺少參數時,在函數體內違背傳入的參數值為undefine
    多傳入的參數在函數體內通過arguments/rest參數(ES6引入)訪問
    rest是未定義的剩余參數數組,arguments是所有的參數對象

    let multimax = function(a, ...remainingNumbers) {
        remainingNumbers.sort((d1,d2)=>d1-d2)
        allArgument = Array.from(arguments)       //ES6 轉成數組
        return a * remainingNumbers[0]
    }
    console.log(multimax(3,8,1,7,6,5))
    
    let func = function(a,b) {      //"use strict"可消除別名特性
        let c = a
        console.log(arguments[0], a, c)
        a = 100
        console.log(arguments[0], a, c)
        arguments[0]=10000
        console.log(arguments[0], a, c)
    }
    func(1)
    
  • 調用

    • 函數上下文 function context

      • 每次函數調用,都會關聯一個特定的函數上下文,即一個object或undefined值,作為一個隱式參數被傳遞到函數體中,對應的參數名稱是this
      • 在非嚴格模式下,函數上下文為global object, 而在嚴格模式下函數上下文為undefine值
      • 用以聯系起function和被賦值的property

      new.target的值為undefined,則函數調用前沒有new,否則有

    • 作為函數/方法調用:命名約定首字母小寫

      • 在原型鏈上的表現 - 函數來自遠方,而this始終是當前對象
    • 作為構造函數調用:命名約定首字母大寫

      • 在前面加上new關鍵詞,以更加方便地創建多個具有足夠共性的obj
      • 如果不return this則返回值正常返回,new創建的obj被忽略
    • 通過apply或call方法調用

      • 隨意調用函數時的函數上下文

      • x.call(thisArg, ...args) x.apply(thisArg, argArray)
        第一個參數是調用函數上下文
        第二個參數call是以列表表示的傳入參數,apply要用數組
        返回值是以thisArg為上下文,對x調用的返回值

        大概是申請了個symbol 關聯方法,最后再刪除

  • 其他

    • bind 方法 x.bind(thisArg, ...args)
      • 返回一個函數,行為與x完全相同;上下文被固化為thisArg;
      • ...args是綁定的參數
  • 箭頭函數

    • 箭頭函數不能作為構造函數,也沒有this,arguments這兩個隱式參數;
    • 箭頭函數定義中出現的this參數在箭頭函數創建時固化為當時環境中的this參數,永不再變;==function context==
  • 閉包

    • 當?個函數對象被創建時,同時還創建了?個閉包
      其中包含: 該函數、以及在此時可以訪問到的所有變量
    • 用途是信息封裝,只用函數才能調用
    • 實現方式:function execution context & lexical environment
      • FEC: 每一次函數調用,通常會創建一個新的函數上下文
        函數調用結束后,運行上下文通常會被拋棄
        ES程序的運行會形成由“函數運行上下文”構成的棧
      • 詞法環境是專門為閉包設計的,無法顯式訪問
        由代碼塊和函數構成,代碼片段的每一次運行都會創建新的詞法環境
      • 當一個函數被創建時,創建這個函數的代碼片段所關聯的詞法環境會被放到[[Environment]]的internal slot中;
        當一個函數被調用時,一個函數運行上下文被創建壓到棧頂,同時為函數運行上下文創建一個詞法環境,將該詞法環境的外層詞法環境設為該函數[[Environment]]的值

<img src="pic/ExecuteNow.png" style="zoom:60%">

Object

  • 常見方法:

    key in obj - 尋找指定的key在不在這個obj上,或者對應原型鏈上

    .hasOwnProperty(key) - 尋找這個key在不在這個obj上

    .getOwnPropertyNames(obj) 返回數組,包含obj所有string類型的key

    .getOwnPropertySymbols(obj) 返回數組,包含obj所有symbol類型的key

  • Iterable object:
    具有一個key為Symbol.iterator的屬性,這個屬性的值是一個函數,函數會返回一個iterator;包括Array, Map, Set, String, auguments

    • iterator是一個object,具有next方法,對它的一次調用返回一個obj{done, value}
    • for-of 循環語句(value)
  • Collections: Array, Map, Set
    任何可遍歷的obj都可以傳到new里面構造

    • Array:

      • push, pop, unshift, shift, splice(start,num,...insert), slice(start,end), indexOf(value), LastIndexOf(value), findIndex(滿足條件), sort((v1,v2)=>{return v1<v2? -1: (v1>v2? 1:0)})

      • splice和slice都是返回start~end的東西

      • forEach((v,i,owner)=>{}) 是接受三個參數的;
        map接收回調函數,按順序對每個值應用該函數將這個值變成另一個值放進新數組
        every, some

        const pets=[{name:'dog'},{name:'cat'},{name:'snake'}]
        if pets.every(pet=>'name' in pet)
          const names=pets.map(pet=>pet.name)
        // names=['dog','cat','snake']
        

        find找到第一個為止,filter把所有滿足的放進數組

      • reduce

        const num = [1,2,3,4,5]
        const sum = num.reduce((sum,v)=>sum+v, 0)
        
    • Map: 任何類型的值都能作為key

      • set(key,value), get(key), size, has(key), delete(key), clear(), forEach((value,key,owner)=>{})
    • Set: 由無重復值形成的有序列表

      • add(value), size, has(value), delete(value)
  • Property Descriptor
    一個object,其中包含若干property,用于對所在property行為進行描述;使用defineProperty(obj,propKey,propDes)來修改

    <img src="pic/PropertyDescriptor.png" style="zoom:60%">

    ==考點==:configurable被置為假,在writable為true時要么可以改false要么改值,其他均不行

    • 通過getter和setter訪問property
  • Prototype

    • constructor提供了基于obj引用constructor的方法

    在Javascript語言中,要是想仿真C++類的關系中,使用原型鏈的方式可以實現。==考點:理解例子==

    ?

    • class
    • const Person = function(name) {
        this.name = name
      }
      Person.prototype.getName = function() {
        return this.name
      }                          //Person關聯的object加入一個函數
      const xie = new Person("shelly") 
      console.log(xie.getName()) //xie->對象->[[Prototype]]有這個函數
      
    class Person {
        constructor(name) {
            this.name = name
        }
        getName() {
            return this.name
        }
    }
    
    • extends
    class Mammal {}
    class Person extend Mammal (){
        constructor() {
          //  ...
        }
        getWeight() {
            return super.getWeight
        }
    }
    
    • instanceof: 判斷一個obj是否在某個構造函數的原型鏈上
  • 析構操作

    • 一些例子

      /*對Object的析構*/
      let node = {
          type: "identifier"
          name: "foo"
          loc: {
              start:{
                  line: 1
                  coloum: 2
              }
          }
      range:[startIndex]
      }
      let {type, name} = node  //要有=,不能=undefined/null
      ({type, name} = node)    //提取obj型函數參數的特定property
      let {name: localname = "bar"} = node //缺省 不同名
      let {loc:{start:{line}}, range:[startIndex]} = node
      
      /*對Array的析構*/
      let colors = ["red", undefined,"blue",["pink","yellow"]]
      let [1st, 2ed = "grey"] = colors
      let [, , 3rd] = colors
      let [,,,[,4in]] = colors    //"yellow"
      let [5th, ...rest] = colors
      
      /*變量值交換*/
      let [1st, 2ed] = [1st, 2ed]
      
      /*優秀例子*/
      function setCookie(name, value, {secure, path} = {}){
          secure = 1 - secure
      }
      

類型轉換

這節太復雜了,自己看課件算了

很多時候,javascript會以顯式/隱式的方式將一種類型的值轉換為另一種類型的值;ES6定義了一組抽象操作;

  • 一組抽象操作(看課件,內容過多)
    • ToPrimitive(input, preferredType)
    • OrdinaryToPrimitive(input, prefferedType)
    • ToBoolean(input) - N0fun
    • ToNumber
    • ToString
    • ToObject
  • ?
  • && || 的行為
  • == 抽象相等,比較過程中允許類型轉換; ===嚴格相等,比較過程中不允許進行類型轉換。

Web頁面編程

Html內容, CSS形式, JavaScript行為 -> DOM樹

  • 元素選擇和修改

      `preventDefault()` 防止href為空時的跳到新頁面的缺省行為
    

    getElementById getElementsByTagName getElementsByClassName

document.addEventListener("DOMContentLoaded",()=>{
    const div = document.querySelector("div")
    console.log(div.style)
})

? getAttribute setAttribute(attr,value)

? CSS信息以嵌入式或鏈接式樣式表中的信息時無法直接從元素中獲得

? window.getComputedStyle(ele).getPropertyValue(propNameStr)

? 對于樣式表里面的內容加入 !important 可提高優先級,避免被改動

  • [Web頁面的事件處理流程] 當處理完一個宏任務后,會立刻按序處理所有的微任務,知道所有微任務都被處理完后才會處理下一個宏任務;如果可能,瀏覽器會確保每秒60幀,一個宏任務及其所產生的微任務應能在16ms完成

  • 定時器

    const id = setTimeout(func,delay) 延遲delay毫秒把事件加入函數隊列

    setInterval(func,delay) 每間隔delay毫秒便嘗試將事件加入函數隊列,當任務隊列中還存在未處理的同源interval事件時interval對應函數時不會加入隊列

    clearTimeout(id) 函數尚未被觸發時取消定時器行為

  • Web頁面中的事件處理

    • 處理計算密集型操作

    • 事件在DOM中的傳播:默認捕獲從外向內,冒泡從內向外。

      • addEventListener(type,func,useCapture)
        useCapture默認是假,事件冒到它才會調用,否則監聽了就調用了

        const tb = document.querySelector("tbody")
        tb.addEventListener("click",function(e)){
          if(e.target.tagName.toLowerCase()=="td")
          e.target.style.backgroundColor = "yellow"
        }  //e.target是事件發生在的html元素
        
    • 自定義事件const Myevent = new CustomEvent(eventType, {detail: eventDetail})

Js異步編程

  • 如果一個任務處理函數用時過長,會降低整個應用的并發程度或處理效率。為了提高程序的并發程度或處理效率,需要異步編程。情境:計算密集,IO密集。

    • 將計算密集型任務拆分為一組細粒度的子任務(例如表格拆分定時創建,在完成一個子任務后,把下一個子任務加入任務隊列setTimeout(nextTask,0)
    • 使用異步讀取文件或異步接收網絡數據的函數。在啟動IO任務時傳入回調函數;然后程序不必阻塞等待IO任務完成,而是繼續執行后面的代碼。當IO任務完成后,把IO完成事件加入任務隊列。
  • Generator函數

    • 把函數本身做的事分為小的塊,由關鍵詞yield來控制。
    • 可以視為一個狀態機。
    • return的值存在遍歷器的value里面。
    function * likes(){
        while(true)
          yield "likes"
    }
    function * PersonGenerator(){
        yield "shelly"
        yield * likes()
        yield "gary"
    }
    for (let person of PersonGenerator()) 
        console.log(person)
    
    • 與Generator函數進行雙向通訊

      • 通過next()從generator函數獲得數據,通過next()的參數向generator傳入數據
      • 向generator函數拋入異常;
      let [a,b,c]=yield "hello"
      let rst = 
      
      
  • Promise對象

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容