一、JS基础
1. js引入:<script>alert('111')</script>,<script language="javascript" src="myJs.js"></script>
2. 注释:单行注释 // ,多行注释 /* 注释 */
3. 数据类型以及转化:
简单数据类型:string、number、boolean、null、undefined、symbol(ES6新增)
复杂数据类型:object
typeof:NaN 的数据类型是 number,NaN不等于任何值,包括它本身,null 的数据类型是 object,数组(Array)的数据类型是 object
instanceof :判断对象的原型链,({}) instanceof Array // false,([]) instanceof Array // true ([]) instanceof Object//true
Number() :原始类型:字符串如果不可以被解析为数值,返回 NaN,null转为数值时为0,undefined:转成 NaN;对象: valueof=》tostring=》number(),参数是对象时,将返回NaN,除非是包含单个数值的数组,parseInt('1234abc') // 1234,parseFloat('0256.25.35') // 256.25
String():原始类型:原值的字符串;对象:"[object Object]";数组:数组的字符串形式,与Number的调用顺序相反 tostring=》valueof=》string()
Boolean():空数组([])和空对象({})对应的布尔值,都是true,Boolean(NaN) // false
Boolean(Infinity) // true
0.1 + 0.2 !== 0.3//由于浮点数不是精确的数值,js需要转成二进制计算,0.000110011……由于存储空间有限,最后计算机会舍弃后面的数字,所以我们最后就只能得到一个近似值,确实需要计算的话用Math.abs(a-b)<Number.EPSILON来表示是否相等,Number.EPSILON为2^-52
0 / 0 // NaN
parseInt的参数不是字符串,则会先转为字符串再转换,字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为 数字的字符,就不再进行下去,number则是一次性,isNaN('Hello') // true相当于isNaN(Number('Hello')) // true
特殊例子:null == undefined、undefined != 0、null != 0、null !== undefined
4. 字符窜:length属性,字符串拼接ES6的eg: `${name}`,常用方法:
concat():用于连接两个或多个字符串
indexOf():返回某个指定的子字符串在字符串中第一次出现的位置,从0开始,大小写敏感,没找到返回-1
match():返回所有查找的关键字内容的数组,没有的话返回null,eg:"To be or not to be".match(/to/ig)返回["To", "to"]
search(): 返回模式第一个匹配的位置索引,如果没找到则返回-1
replace():用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串,第一个参数为regexp或者字符串,第二个参数表示替换的字符
slice():返回提取的子字符串;只有1个参数,返回参数下标到结尾处的所有字符串,两个参数a,b则提取[a,b),substring()方法类似
substr():第一个参数为开始位置,第二个参数表示返回的子字符串数量
split():把字符串分割成字符串数组,第一个参数表示分隔符,第二个参数表示返回数组的最大长度
toString():转换为一个字符串,并返回结果
trim() :用于删除字符串的头尾空格,不会改变原始字符串
startsWith()、endsWith()、includes()、toLocaleLowerCase()和 toLocaleUpperCase()
5. 数组遍历以及数组的其他方法:
检测是否是数组:Array.isArray()
①for in :for(let key in arr) {console.log(arr[key]);}
②foreach 不会改变元素,不会返回新数组:arr.foreach((value,index)=>{})
③map遍历数组,对每个元素进行处理,返回一个新数组:let arr2 = arr.map((value,index)=>{value++ return value})
④some遍历数组,在回调里进行判断,返回 true 或 false ,当有一个元素满足条件时就停止遍历并返回true;当全部的元素都 不满足要求时,返回false:let bool = arr.some((value,index)=>{return value>3})
⑤every遍历数组,当有一个元素不满足条件时就停止遍历并返回false;当全部元素都满足时,返回true
⑥filter遍历数组,在回调函数里进行条件判断,当结果为true时,将该元素返回,组成一个新数组
⑦reduce(callback(total, currentValue, currentIndex, arr),init) init为初始值,可以省略,(上一个归并值、当前项、当前项的索引和数组本身)
every、filter、forEach、map、some传给每个方法的函数接收 3 个参数:数组元素、元素索引和数组本身,都不改变调用它们的数组
数组的其他方法:
push:末端添加一个或多个元素,并返回添加新元素后的数组长度
pop:删除数组的最后一个元素,并返回该元素
shift:删除数组的第一个元素,并返回该元素
unshift:在数组的第一个位置添加元素,并返回添加新元素后的数组长度
join(符号):[1,2,3,4].join(' | ') // '1 | 2 | 3 | 4'
concat:['hello'].concat(['world'])// ["hello", "world"]返回一个新数组,原数组不变,如果传入一个或多个数组,则 concat()会把这些数组的每一项都添加到结果数组。 如果参数不是数组,则直接把它们添加到结果数组末尾
reverse:颠倒排列数组元素,返回改变后的数组,会改变原始数组
slice(start,end):提取目标数组的一部分,不包含结束索引对应的元素,返回一个新数组,原数组不变,可以将类似数组的对象转为真正的数组例如 arguments对象,let arr = Array.prototype.slice.call(arrayLike);
splice(index,num,item1,..,itemX):用于删除原数组的一些成员,并可以在删除的位置添加新成员,返回值是被删除的元素(数组)
sort:默认按照字典顺序排序,可以接收一个比较函数,[10111, 1101, 111].sort(function (a, b) {return a - b;})
indexOf()、lastIndexOf():返回数组下标或者-1,includes()返回Boolean值
find():返回对象或者undefined
findIndex():返回数组下标或者-1
6. 对象:相当于一张散列表
访问:obj.xxx或者obj['xxx']
释放对象内存:delete obj.xxx;
对象数据属性:要修改属性的默认特性,就必须使用 Object.defineProperty(对象,属性的名称,描述符对象)方法,多个属性可用Object.defineProperties(obj,{})
[[Configurable]]:是否可通过delete删除属性
[[Enumerable]]:是否可通过for in返回
[[Writable]]:是否可以修改属性值
[[Value]]:属性值
对象访问器属性:访问器属性不包含数据值
[[Configurable]]:是否可通过delete删除属性
[[Enumerable]]:是否可通过for in返回
[[Get]]:获取函数
[[Set]]:设置函数
获取属性方法:Object.getOwnPropertyDescriptor(obj,key),
Object.getOwnPropertyDescriptors(obj)
对象解构赋值:const { a: anotherNameA, b: anotherNameB = 123 } = obj
7. 对象遍历
keys(): 返回数组的索引(结果为数组),包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性),先以升序枚举数值键,然后以插入顺序枚举字符串和符号键
values(): 返回数组的元素(结果为数组)
entries(): 返回数组的索引/值对(结果为二维数组)
②for in :循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)
8. ||:将会返回第一个不是false的值 或者最后一个值(如果全部都是FALSE的话),不一定是bool值
9. 函数
arguments参数:可以访问所有该函数的传入值,例如n个,arguments是类数组对象(但不是 Array 的实例),箭头函数没有arguments
function abc() {
for(let i=0; i< arguments.length; i++) {
window.alert(arguments[i]);
}
}
ECMAScript 中的所有参数都按值传递的。不可能按引用传递参数。如果把对象作 为参数传递,那么传递的值就是这个对象的引用
在标准函数中,this 引用的是把函数当成方法调用的上下文对象
在箭头函数中,this引用的是定义箭头函数的上下文
10. 函数中传入值还是地址的区别:第一个输出还是900没变,第二个改变了,因为传入地址导致堆的原数据改变了
11. 防止鼠标右键拷贝:<body οncοntextmenu="return false"></body>
防止用户选中内容用ctrl+c复制:<body onselectstart="return false"></body>
12. DOM
属性:nodeType,nodeName,nodeValue,childNodes,parentNode,previousSibling,nextSibling
document对象 :title属性(显示在浏览器标签)
getElementById():id选择器
getElementByClassName():类选择器
getElementsByName():通过name获取,主要用于checkbox
getElementsByTagName():通过标签名获取
createElement(标签名):动态的创建一个节点
appendchild(节点名):(要在节点里添加内容才能显示)添加节点到一个已知的节点下作为子节点,在这个节点的childNodes的末尾加入,返回值为这个节点
removeChild(节点名):删除一个元素,需要先知道父元素,可以用 xxx.parentNode.removeChild(xxx)
insertBefore(新节点,参照节点):参照节点为null则功能和appendChild一样
replaceChild(新节点,被替换节点):
element:其中class属性用className获取,innerHtml、innerText、focus()、blur()
createElement(标签名):创建元素
getAttribute(属性名):访问style属性时返回css字符窜,而用element.style返回对象,访 问事件属性返回一段js代码,而用element.事件返回一个函数
setAttribute(属性名,属性值):多用于设置自定义属性
removeAttribute(属性名):彻底删除该属性(包括属性值)
querySelector('.myclass'):通过各种选择器返回匹配的第一个节点
querySelectorAll('#app'):返回nodelist(快照,不是实时的)
classList属性:主要用于删除某个类名,例如div.classList.remove("disabled")
dataset属性:
<div id="myDiv" data-appId="12345" data-myname="Nicholas"></div>
let div = document.getElementById("myDiv");
// 取得自定义数据属性的值
let myName = div.dataset.myname;
// 设置自定义数据属性的值
div.dataset.myname = "Michael";
innerHTML:返回元素里面的html字符窜,可读可写
outerHTML:返回包含该元素的html字符窜,可读可写
style属性:元素的样式,myDiv.style.backgroundColor = "red",特别的float写cssFloat, style的cssText属性可以直接读和写样式,removeProperty(属性名), setProperty(propertyName, value, priority),priority可以是'important'
scrollIntoView方法:div.scrollIntoView({behavior: 'smooth', block: 'start'});
尺寸:
offsetHeight:包括padding、border、水平滚动条、content
clientHeight:包括padding、content
offsetTop:元素上边框外侧距离最近父元素上边框内侧
scrollHeight:没有滚动条出现时,元素内容的总高度
scrollLeft:内容区左侧隐藏的像素数,设置这个属性可以改变元素的滚动位置。
scrollTop:包含border-top,没有滚动条时为0
getBoundingClientRect():该方法获取元素的left、top、right、bottom、height 和 width
13. 正则表达式RegExp:
隐式创建:let reg = /正则表达式/gi,显式创建:let reg = new RegExp(正则表达式,“gi”);g表示全局,i表示忽略大小写
exec():检索想要找的内容,结果返回一个数组,第一个值为找到的文本内容,找不到时返回null
属性:index、lastindex、leftContext、rightContext
元字符限定符:{n}表示出现次数,{n,m}表示最少出现n次最多m次,满足贪婪匹配,即尽可能的匹配更多的字符串,+表 示出现1次以上,*表示出现0次及以上,?表示0到1次
字符匹配符:[a-z]表示小写字母a-z,[A-Z],[0-9],[^a-z]匹配不是a-z中的任意一个字符
定位符:^表示匹配目标字符串的开始位置,$表示匹配目标字符串结束位置
14. 声明函数的办法:函数的声明function(){},函数表达式(末尾加‘;’),只有函数声明会提升
函数执行时所在的作用域,是定义时的作用域,而不是调用时所在的作用域
function(a, b, ...rest) {}:rest表示剩余的参数
15.Json常用方法:转为字符串Json.stringify(),转为对象Json.parse()
16.ES6新增内容:
Map:与对象类似,但是可以用复杂类型做key,
Set:似于数组,但是成员的值都是唯一的,没有重复
结构赋值:let { bar,foo } = { foo: "aaa", bar: "bbb" },let [x, y = 'b'] = ['a']; // x='a', y='b'
17. 运算符:
“+”:字符串相连接,运算子是对象,必须先转成原始类型的值,然后再相加,首先valueOf,再toString(特例Date对象的实 例,那么会优先执行toString)
“比较运算符”:字符串按照字典顺序(Unicode )进行比较,如果两个运算子都是原始类型的值,则是先转成数值再比较,如 果运算子是对象,会转为原始类型的值,再进行比较,两个复合类型(对象、数组、函数)比较时,比较它们是否指向同一 个地址。undefined和null与其他类型的值比较时,结果都为false,它们互相比较相等时结果为true。
18. 事件
事件流:捕获阶段(window到目标)、到达目标、冒泡阶段,focus和blur不会冒泡
e.stopPropagation():事件停止传播,e.preventDefault:取消浏览器的默认行为
addEventListener(事件名,处理函数,布尔值):布尔值true表示在捕获阶段触发
removeEventListener:好用的浏览器兼容库(add-dom-event-listener)
模拟事件:document.createEvent(事件类型),UIEvents、MouseEvents、HTMLEvents
eg:
let btn = document.getElementById("myBtn");
// 创建 event 对象
let event = document.createEvent("MouseEvents");
// 初始化 event 对象
event.initMouseEvent("click", true, true, document.defaultView,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
// 触发事件
btn.dispatchEvent(event)
19.Bom
window:用var定义一个全局变量会挂载在window上,而用let或者const则不会,常用方法: window.scrollTo({ left: 100, top: 100, behavior: 'smooth' }), window.open(url,'_blank',"height=400,width=400,top=10,left=10,resizable=yes")
location:location.href="http://xxxxx",search属性用来获取query参数,location.replace(), location.reload(true):true表示不适用浏览器缓存
navigator:一般用userAgent属性来判断什么客户端, geolocation.getCurrentPosition(fun1,errFun)获得地理位置, onLine判断浏览器是否连网
history:history.go(x),x为负数表示后退,length属性表示页面栈
二、JS难点
1. 变量提升:先解析代码,获取所有被声明的变量,提升变量,但是没有提升赋值,函数提升优先于变量提升,且不会被变量声明覆盖,但是会被变量赋值之后覆盖
console.log(a);var a=1;//输出undefined,但是不会报错 ===var a;console.log(a);a=1;
2. 原型链:
每个函数都有prototype,指向原型对象(Person prototype),原型对象自动获得一个名为 constructor 的属性指回与之关联的构 造函数,每个对象实例都有一个_proto_指向创建该对象的构造函数的原型,所有原型的原型为Object函数的原型,最终源头为null
返回原型对象:Object.getPrototypeOf(实例obj)
重写一个对象的原型继承关系:Object.setPrototypeOf(a,b),a链到b(一般不用)
实例自己本身是否拥有改属性:obj.hasOwnProperty(key)
只要给对象实例添加一个属性,这个属性就会遮蔽原型对象上的同名属性,使用 delete 操作符可以完全删除实例上的这个属性
in操作符:key in obj (key是否在obj的原型链上)
function Person() {}
Person.prototype = {
name: "Nicholas",
age: 29,
job: "Software Engineer",
sayName() {
console.log(this.name);
},
// constructor: Person // 手动将constructor指向Person,这时候的[[Enumerable]]为true
};
// 恢复 constructor 属性
Object.defineProperty(Person.prototype, "constructor", {
enumerable: false,
value: Person
})
以上例子的Person.prototype的constructor就不再指向Person了,而是指向Object
先重构Person.prototype再new实例和先new实例再重构Person.prototype是不一样的
先new实例
3. 异步操作:异步任务的写法通常是回调函数。一旦异步任务重新进入主线程,就会执行对应的回调函数
promise:状态有未完成、完成(成功、失败),变化:①未完成=>成功,返回一个value;②未完成=>失败,抛出一个error
promise.all([请求1,请求2]).then() :用于不同url的两个请求
async、await:async function xxx(){ await ajax请求}
4. 深、浅拷贝,直接赋值
浅拷贝:Object.assign({},{name: 'ljh'})或者let a= {age: 5}; let b = {...a}
深拷贝:对象中还有对象,用JSON.parse(JSON.stringify(obj))
大致解析图:
当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,改变某一个不会影响另外一个的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源
5. 防抖和节流
防抖:将多次执行变为最后一次执行,在n秒内只能执行一次,如果在n秒内触发了事件则重新计算时间,eg防止重复点击某个按钮、滚动条滚动
function debounce(fn,delay){
let timer = null //借助闭包
return function() {
if(timer){
clearTimeout(timer)
}
timer = setTimeout(fn,delay) // 简化写法
}
}
节流:连续触发事件,但在n秒内只执行一次,将多次执行变成每隔一段时间执行,例如输入框关键字搜索
function throttle(fn,delay){
let valid = true
return function() {
if(!valid){
//休息时间 暂不接客
return false
}
// 工作时间,执行函数并且在间隔期内把状态位设为无效
valid = false
setTimeout(() => {
fn()
valid = true;
}, delay)
}
}
6. class
构造函数里的属性和方法会变成实例的属性和方法,普通方法会挂载在类的原型上,而静态方法则只有类自己使用
class Person {
constructor() {
// 添加到 this 的所有内容都会存在于不同的实例上
this.locate = () => console.log('instance', this);
}
// 定义在类的原型对象上
locate() {
console.log('prototype', this);
}
// 定义在类本身上
static locate() {
console.log('class', this);
}
}
let p = new Person();
p.locate(); // instance, Person {}
Person.prototype.locate(); // prototype, {constructor: ... }
Person.locate(); // class, class Person {}
new的过程:类实例化时传入的参数会用作构造函数的参数
- 新生成了一个对象
- 链接到原型(对象的_proto_指向构造函数对象的prototype)
- 绑定 this(this 指向新对象)
- 返回新对象(如果构造函数返回非空对象,则返回它)
function Foo() {
return this;
}
Foo.getName = function () {
console.log('1');
};
Foo.prototype.getName = function () {
console.log('2');
};
new Foo.getName(); // -> 1
new Foo().getName(); // -> 2
new Foo()
的优先级大于 new Foo,
对于第一个函数来说,先执行了 Foo.getName()
,所以结果为 1;对于后者来说,先执 行 new Foo()
产生了一个实例,然后通过原型链找到了 Foo
上的 getName
函数,所以结果为 2
继承:extends,类和函数都可以继承
派生类的方法可以通过 super 关键字引用它们的原型, 只能在派生类构造函数和静态方法中使用,react中经常可见,不能在调用 super()之前引用 this。
super(); // 相当于 super.constructor()
7. this:
function foo() {
console.log(this.a)
}
var a = 1
foo()
var obj = {
a: 2,
foo: foo
}
obj.foo()
// 以上两者情况 `this` 只依赖于调用函数前的对象,优先级是第二个情况大于第一个情况
// 以下情况是优先级最高的,`this` 只会绑定在 `c` 上,不会被任何方式修改 `this` 指向
var c = new foo()
c.a = 3
console.log(c.a)
// 还有种就是利用 call,apply,bind 改变 this,这个优先级仅次于 new
8. 闭包:指引用了另一个函数作用域中变量的函数 ,A 返回了一个函数 B,并且函数 B 中使用了函数 A 的变量,函数 B 就被称为闭包
function A() {
let a = 1
function B() {
console.log(a)
}
return B
}
闭包会保留它们包含函数的作用域,所以比其他函数更占用内存
9. 模块化:AMD(RequireJS)、CMD(SeaJS)、CommonJs、ES6
AMD:通过define()函数定义,第一个参数是一个数组,里面定义一些需要依赖的包,第二个参数是一个回调函数,通过变量 来引用模块里面的方法,最后通过return来输出
CMD:define()定义,没有依赖前置,通过require加载插件,即插即用
CommonJs:module.exports={}或者exports.xxx=...,前端浏览器里面并不支持module.exports,一般是node.js后端使用的
ES6:export/import
10. 对象的创建方式
①工厂模式:用函数来封装创建对象的细节,在函数里面创建对象并返回对象
②构造函数模式:给构造函数传递不同的参数,利用new来创建不同实例
③原型模式:用Person.prototype.xxx=‘a’来定义原型的属性,之后用new创建实例,一旦原型属性改变,所有实例属性也改变
④混合构造函数和原型模式:构造函数定义私有属性,原型定义共有属性和方法
⑤动态原型模式 、寄生构造函数模式、稳妥构造函数模式
11. 继承
父类(继承谁,提供继承的属性)
①原型链继承:让新实例的原型等于父类的实例
特点:实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性
缺点:新实例无法向父类构造函数传参,继承单一,所有新实例都会共享父类原型的属性
②构造函数继承:用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自执行)
特点:继承父类构造函数的属性没有继承父类原型的属性,可继承多个构造函数属性(call),在子实例中可向父实例传参
缺点:只能继承父类构造函数的属性,无法实现构造函数的复用,每个新实例都有父类构造函数的副本,臃肿
③组合继承(原型链继承和借用构造函数继承):结合了两种模式的优点,传参和复用
特点:可以继承父类原型上的属性,可以传参,可复用,每个新实例引入的构造函数属性是私有的
缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数
④原型式继承、寄生式继承、寄生组合式继承
12. call、bind、apply
call和apply都可以解决this指向,区别是第二个参数call接收的是一个列表而apply接收一个数组,call 方法第一个参数是要绑定给this的值,后面传入的是一个参数列表,当第一个参数为null、undefined的时候,默认指向window。apply接受两个参数,第一个参数是要绑定给this的值,第二个参数是一个参数数组。当第一个参数为null、undefined的时候,默认指向window。
let a = {
value: 1
}
function getValue(name, age) {
console.log(name)
console.log(age)
console.log(this.value)
}
getValue.call(a, 'yck', '24')
getValue.apply(a, ['yck', '24'])
bind的第一个参数是this的指向,从第二个参数开始是接收的参数列表。区别在于bind方法返回值是函数以及bind接收的参数列表的使用。、
var obj = {
name: 'Dot'
}
function printName() {
console.log(this.name)
}
var dot = printName.bind(obj)
console.log(dot) // function () { … }
dot() // Dot
function fn(a, b, c) {
console.log(a, b, c);
}
var fn1 = fn.bind(null, 'Dot');
fn('A', 'B', 'C'); // A B C
fn1('A', 'B', 'C'); // Dot A B
fn1('B', 'C'); // Dot B C
fn.call(null, 'Dot'); // Dot undefined undefined
13.模块化:
CommonJS:exports 和 require
var moduleB = require('./moduleB');
module.exports = {
stuff: moduleB.doStuff();
};
AMD:define
define('moduleA', ['require', 'exports'], function(require, exports) {
var moduleB = require('moduleB');
exports.stuff = moduleB.doStuff();
});
ES6:export 和 import,as重命名,default默认导出只能一个,一个文件可以有多个export
import和require的区别:
模块加载时间:require是运行时加载,而import是编译时加载,并且会提升到整个模块头部
模块本质:require模块就是对象,输入时必须查找对象属性,import的模块不是对象,而是通过 export 命令显式指定输出的代码
// CommonJS模块
let { exists, readFile } = require('fs');
// 等同于
let fs = require('fs');
let exists = fs.exists;
let readfile = fs.readfile;
// ES6模块 import { exists, readFile } from 'fs';
严格模式:CommonJs模块默认采用非严格模式,ES6 的模块自动采用严格模式,CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用
14.Map和Set
Map:与object类似,但是可以用任意类型作为键,长度属性size
const newMap = new Map([[key: 'value']]),传入一个二维数组
方法:set(key, value),get(key),has(key),set()方法返回映射实例,可以把多个操作连缀起来,
delete(key)和 clear()
Set:const s1 = new Set(["val1", "val2", "val3"]),传入数组,长度属性size
方法:add(value),has(value),delete(value), clear(),add()方法返回映射实例,可以把多个操作连缀 起来,集合直接转成数组const array = [...set]
15、异步函数和Promise
promise:new Promise((resolve,reject) => {...})
Promise.all([]):按照数组排序返回结果数组,只要有一个reject,就进入catch,返回最先reject的请求错误
Promise.race():返回最先结束pending状态的请求,无论reject还是resolve
async:用于声明异步函数,函数里有return的话就是期约,没有的话就是普通函数
await:暂停异步函数代码的执行,让出 JavaScript 运行时的执行线程,必须在异步函数里使用, 也就是在async函数里
用异步函数可产生一个sleep函数
16、动画和canvas
requestAnimationFrame(function):接收一个要在重绘屏幕前调用的函数,返回一个请求 ID
cancelAnimationFrame(动画id)
canvas:getContext('2d')获取上下文引用
toDataURL("image/png"):canvas转成图片
填充和描边
let context = drawing.getContext("2d");
context.strokeStyle = "red";
context.fillStyle = "#0000ff";
17、跨文档消息XDM:在不同执行上下文(如不 同工作线程或不同源的页面)间传递信息的能力
postMessage(message,目标接收源),接收到 XDM 消息后,window 对象上会触发 message 事件
18、元素拖动
dragstart-drag-dragend dragenter-dragover-drop
19、错误处理
try { return 2; } catch (error){ console.log(error.message) return 1; } finally { return 0; }
抛出错误:throw new Error("process(): Argument must be an array.");
20、网络请求
最初的请求XMLHttpRequest:
let xhr = new XMLHttpRequest();
xhr.open("get", "example.txt", false);
xhr.send(null);
请求体中FormData类型:let data = new FormData(); data.append("name", "Nicholas");
跨源资源共享(CORS):协议、域名、端口三者之间任意一个与当前页面url不同
解决方法:1、JSONP;
2、服务器端设置Access-Control-Allow-Origin;
3、如果带cookie前端还要axios.defaults.withCredentials = true
4、fetch()
5、如果是本地开发,可以用webpack本地代理
6、Nginx反向代理
Web Socket:
let socket = new WebSocket("ws://www.example.com/server.php");
let stringData = "Hello world!";
let arrayBufferData = Uint8Array.from(['f', 'o', 'o']);
let blobData = new Blob(['f', 'o', 'o']);
socket.send(stringData);
socket.send(arrayBufferData.buffer);
socket.send(blobData);
socket.close();
socket.onmessage = function(event) {
let data = event.data;
// 对数据执行某些操作
};
socket.onopen = function() {
alert("Connection established.");
};
socket.onerror = function() {
alert("Connection error.");
};
socket.onclose = function() {
alert("Connection closed.");
};
21、客户端存储
cookie:document.cookie = cookieText(可采取js cookie库辅助,目前用的较少)
storage:sessionStorage(会话级)、localstorage(永久),都是同步操作可马上读,每当 Storage 对象发生变化时,都会在文档上触发 storage 事件
getItem()、setItem()、removeItem()、clear()