0%

JavaScript 高级程序设计笔记

script

  • async 表示立即开始下载脚本,但不能阻止其他页面动作,异步下载与执行。不应该在加载期间修改 DOM,会保证在 load 事件前执行,但可能会在 DOMContentLoaded 之前或者之后执行
    • 不需要等待其他脚本,也不能阻塞文档渲染,不能保证执行顺序
  • crossorigin
    • crossorigin="anonymous" 表示不必设置请求凭据标志(允许跨域)
    • ="use-credentials"
  • defer 表示脚本可以延迟到文档完全被解析和显示之后再执行
    • 在 ie7 及更早的版本对行内佳酿也有用
    • 推迟到渲染完成后执行,原则上按照被列出的顺序执行
  • src 有 src 时,内部代码不执行

var

使用 var 声明的变量会自动提升到函数作用域顶部

函数声明可以提升,但是类定义不能提升

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function fn() {
if (a !== void 0) {
var a = 1
}
console.log(a)
}
// 上面的代码类似下面的代码
function fn() {
var a
if (a !== void 0) {
a = 1
}
// undefined
console.log(a)
}

let

使用 let 声明迭代变量时,JS 引擎在后台会为第个迭代循环声明一个新的迭代亦是

null

null 值表示为一个空对象指针

NaN

Not a Number , 表示本来要返回数值的操作失败了

加法操作符

如果只有一个操作数是字符串,则将另一个操作数转换为字符串,再将两个字符串拼接在一起

原始值

给原始值添加属性不会报错,但不会获取到对应的属性,只有引用 值可以动态添加属性

传递参数

JS 中所有函数传参都是按值传递,传对象时,其实传的是指向这个对象的指针。

按传传递还是按引用传递可以理解 c++的引用

1
2
3
4
5
6
7
8
9
void add(int &num) {
num+=1;
}
int main() {
int num = 2;
add(num);
// 这里的add才是按引用传递,所以num的值为3;
cout<< num;
}

对应非原始值,访问的时个可以理解为按引用访问

执行上下文

每个上下文都有一个关联的变量对象,全局上下文是最外层的上下文

每个函数都有自己的上下文,当执行到函数时,会将函数的上下文推入到一个上下文栈中(执行栈)

上下文中的代码在执行时会创建变量对象的一个作用域链(JS 是一种静态的作用域,即在定义是作用域链已经固定【shell 为动态作用域】)。代码正在执行的上下文的变量对象始终位于作用域链的前端,如果上下文是函数,则基活动对象(包含argments的对象)用作变量对象

作用域链增强

with / try catch 的 catch 会在作用域链前端临时添加一个上下文

垃圾回收

标记清理

引用计数

循环引用有问题

隐藏类

运行时 V8 会将创建的对象与隐藏类关联起来

原始值包装类型

每当用到某个原始值的方法或者属性时,后台会创建一个相应的原始包装类型的对象,从而暴露出操作原始值的各种方法。

1
2
let s1 = 'hello world'
let s2 = s1.substring(2)

以上的代码,以读模式访问字符串值的任何时候,都会经历

  1. 创建一个 String 类型的实例
  2. 调用实例上的方法
  3. 销毁实例

Math.random()

返回 [0, 1) 左闭右开

定型数组

一旦创建,大小不可变

ArrayBuffer

ArrayBuffer 是所有定型数组及其视图引用的基本单位

可用于在内存中分配特定数量的字节空间

类似 c 语言的 malloc()

读取或者写入 ArrayBuffer 必须通过视图(DataView)

DataView

1
2
const buf = new ArrayBuffer(16)
const view = new DataView(buf)

Object 还是 Map

  • 固定大小的内存,Map 大约可以比 Object 多存储 50%的健值对
  • Map 在插入性能上稍微快点
  • 如果只包含少量的键值对时,Object 有时候的查找速度更快
  • Map 的 delete 比插入和查找更快

WeakMap

  • 弱键
  • 键只能是对象

迭代器协议

迭代器是一种一次性使用的对象,用于迭代与其关联的可迭代对象,迭代器 API 使用 next()方法在可迭代对象中遍历数据

生成器是一种特殊的函数,调用之后会返回一个生成器对象,生成器对象实现了 Iterable 接口。

给对象添加属性

直接给对象添加属性后,对应的 cofigurable enmerable writable 都是 true

使用 Object.defineProperty 是,如果不提供 cofigurable enmerable writable,则默认为 false

null undefined

null 和 undefined 不能被解构,会报错

1
2
3
4
// 解构
const { a } = null
// 扩展运算
const a = { ...null }

new 过程

  1. 在内存中创建一个新对象
  2. 这个新对象的[[prototype]]特性被赋值为构造函数的 prototype属性
  3. 构造函数内部的 this 被赋值为这个新对象(this 指向新对象)
  4. 执行构造函数内部的代码
  5. 如果构造函数返回非空对象,则返回该对象;否则返回刚刚创建的新对象

只要创建一个函数,就会按照特定的规则为这个函数创建一个 prototype 属性(指向原型对象),默认情况下所有原型对象都有一个 constructor 属性,指向与之关联的构造函数。

实例与构造函数的原型之间有直接的联系,与构造函数之间没有

原型层级

通过对象访问属性时,搜索开始于对象实例本身,如果发现了有这个属性,则返回,如果没有找到,则搜索会沿着指针进入原型对象,然后在原型对象上找到属性后返回。

可以通过实例读取原型对象上的值,但不有通过实例重写这些值,如果在实例上添加一个对原型对象同名的属性,就会直接在这个实例上创建这具属性,这个属性会遮住原型对象上的属性。

属性枚举顺序

for-in循环和object.keys()的枚举顺序不确定,取决于 JS 引擎,可能因浏览器面异。

Object.getOwnPropertyNames() Object,getOwnPropertySymbols()Object.assign() 的枚举顺序是确定的,先以升序枚举数值键,然后以插入的顺序枚举字符和符号键

重写原型时记得将 Constructor 指回去

1
2
3
4
5
6
7
8
function Person() {}
Person.prototype = {
constructor: Person,
name: 'a',
hell() {
console.log(this.name)
},
}

箭头函数

箭头函数的 this 引用的是定义箭头函数的上下文

闭包

闭包指的是那些引入了另一个函数作用域变量的函数

闭包在被函数返回之后,其作用域一直保存在内存中,直到闭包被销毁

窗口与像素比

window.devicePixelRatio表示物理像素与逻辑像素之间的缩放系数

CSS 像素为逻辑像素

DOM

如果文档中已经存在的节点传统 appendChild,则这个节点会从之前的位置转移到新位置

insertBefore接收两个参数,插入的节点和参照节点,如果参照节点是 null,则insertBeforappendChild效果相同

replaceChild接收两个参数,要插入的节点和要替换的节点,要替换的节点会被返回并从文档树中完全移除

removeChild被移除的节点从技术上说仍然被同一个文档所拥有,但文档中没有它的位置

把每个页面上的document.domain设置成相同的值,这些页面就可以访问对方的 JS 对象

浏览器对 domain 有限制,一旦放松就不能再收紧

MutationObserver

可以在 DOM 被修改时异步执行回掉

querySelectorAll

querySelectorAll返回的 NodeList 实例一个属性和方法都不缺,但它是一个静态的快照,而非实时的查询。

Children

children 属性是一个 HTMLCollection 只包含元素的 Element 类型的节点。

childNodes 还包含文本节点

鼠标事件

执行顺序

  1. mousedown
  2. mouseup
  3. click
  4. mousedonw
  5. mouseup
  6. click
  7. dbclick

键盘事件

顺序

  1. keydown
  2. keypress
  3. keyup

requestAnimationFrame

requestAnimationFrame 方法接收一个参数,这个参数是一个在重绘屏幕前调用的函数,这个函数就是修改 DOM 样式以及反映下一次重绘有什么变化的地方。

canvas

可以使用toDataURL 方法导出 canva 元素上的图像

  • fillReact
  • stokeRect
  • clearRect

绘制路径

  • 要绘制路径,必须首先调用beginPath
  • arc(x, y, radius, startAngle, endAngle, counterclockwise) 绘制弧线
  • quadraticCurveTo(cx, cy, x, y) 绘制二次贝赛尔曲线
  • drawImage 把现有图像绘制到画布上

document.execCommand

这个方法多用于富文本编辑器

可以接收 3 个参数,要执行的命令、表示浏览器是否为命令提供用户界面的布尔值、执行命令必需的参数

命令列表

1632963900409SVpNHc

SharedArrayBuffer

ArrayBuffer必须在不同的上下文间切换,SharedArrayBuffer则可以被任意多个执行上下文同时使用

template

浏览器原生的<template></template> 标签内的内容不会渲染到页面上

预检请求

CORS 通过一种收预检请求的服务器验证机制,这个请求使用 OPTIONS 方法发送,包含以下内容

  • Origin
  • Access-Control-Request-Method
  • Access-Control-Requet-Headers

预检请求返回后,结果会按响应指定的时间缓存一段时间,只有第一次发送这种类型的请求时才会多发送一次额外的 HTTP 请求

withCredentials用来表明请求是否发送 Cookie

对应Access-Control-Allow-Credentials

JSONP

JSONP格式包含两个部门,回调和数据,回调通过请求动态指定一个函数

数据则作为参数传递给这个函数

Fetch

XMLHttpRequest 可以选择异步,而Fetch则必须是异步

cookie

  • cookie 名不区分大小写
  • 值必须经过 URL 编码
  • HTTP-only 可以在浏览器设置,也可以在服务器设置,但只能在服务器上读取

sessionStrorage

数据只会存储到浏览器关闭

localStorage

数据会保留到缓存被清除前

不同的浏览器对 sessionStrorage 和 localStorage 设置了不同的空间限制,大多数会限制为每个源 5M

IndexedDB数据库与页面源绑定,信息不能跨域共享,每个源有空间限制 Firefox 的限制为 50M,Chrome 为 5M。