- 幻灯片的关键点需要完全看懂,把几个点混在一个题里面
- 死记硬背的成分不太多,点比较小,文字长串
- 填空的一些形式:给出程序,通过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对象