- 幻燈片的關鍵點需要完全看懂,把幾個點混在一個題里面
- 死記硬背的成分不太多,點比較小,文字長串
- 填空的一些形式:給出程序,通過console.log()填空;
問答有一題送分,要規整排版好,寫上兩三個點就差不多了;
編程題會拿一些幻燈片的程序,看懂之后能重寫;
劃重點
運行js ,值和類型,typeof(null)==object
, 未被賦值的變量也是undefined
,聲明數值中前后的0可以忽略,整數判斷,NaN不和自己等,字符串,模板字符串,轉義符,嵌入表達式,==obj混合考察==,delete
操作符-權限,['key'],訪問不存在的屬性-undefined-用什么方式判斷,內置類,不加new,==數組混合==,==數組那幾個方法如slice
==,‘use strict'不用管,先有雞,==變量作用域==,property帶記憶函數,函數參數數目,==rest參數,隱式參數==,bind,走神了漏了很多函數的沒看,global.this,==箭頭函數==,==運行上下文==,閉包說不用管,==詞法環境==題目多,obj的方法們,遍歷器很復雜,for of
,spread
,forEach
,常識性方法們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")
- 共享Symbol類型的值:利用全局的symbol值注冊庫
在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
- built-in obj
-
傳值/傳引用?
根據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
-
- 每個obj相關聯且僅關聯一個Prototype
- 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是綁定的參數
- bind 方法
-
箭頭函數
- 箭頭函數不能作為構造函數,也沒有this,arguments這兩個隱式參數;
- 箭頭函數定義中出現的this參數在箭頭函數創建時固化為當時環境中的this參數,永不再變;==function context==
-
閉包
- 當?個函數對象被創建時,同時還創建了?個閉包
其中包含: 該函數、以及在此時可以訪問到的所有變量 - 用途是信息封裝,只用函數才能調用
- 實現方式:function execution context & lexical environment
- FEC: 每一次函數調用,通常會創建一個新的函數上下文
函數調用結束后,運行上下文通常會被拋棄
ES程序的運行會形成由“函數運行上下文”構成的棧 - 詞法環境是專門為閉包設計的,無法顯式訪問
由代碼塊和函數構成,代碼片段的每一次運行都會創建新的詞法環境 - 當一個函數被創建時,創建這個函數的代碼片段所關聯的詞法環境會被放到[[Environment]]的internal slot中;
當一個函數被調用時,一個函數運行上下文被創建壓到棧頂,同時為函數運行上下文創建一個詞法環境,將該詞法環境的外層詞法環境設為該函數[[Environment]]的值
- FEC: 每一次函數調用,通常會創建一個新的函數上下文
- 當?個函數對象被創建時,同時還創建了?個閉包
<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, someconst 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對象