相关学习推荐:javascript
前言
说起JavaScript,大家都知道是一门脚本语言。那么ES是什么鬼呢?ES全称ECMAScript ,是JavaScript语言的国际标准。
最近总结了条w Y M v 4 B j v $js的基础特性相关的知识点,大家一起看一下吧
1.严格模式
- 使用严格模式,可以在函数内部进行较为严格的全局和局部的错误条件检查
- 严格模式的编译指示,"use strict"
- 创建全局变量,未声明变量,非严格模式下为创建全局变量;严格模式下为抛出ReferenceError
- 对变量调用delete操作符,删除变量,非严格模式下为静默失败;严格模式下为抛9 n ~ r w出ReferenceError
- 操作对象情况下:a,只读属性赋值会抛出TypeError;b,对不可配置的属性使用delete操作符会抛出TypeError;c,为不可扩展的对象添加属性会抛出TypeError。
- 重名属性情况:a,非严格模式下没有错误,以第二个属性为准! 0 D v z =;b,严格模式下会抛出语法错误。
- 函数参数必须唯一,重名参数,在非严格模式下没有错误,只能访问第二个参数;严格模式下,会抛出错误。
function funValue(value) {
value="dada";
a, g x y alert(value); // dada
alert(argument[0]); // 非严格模式:dada
// 严格模式模式 dadaqianduan}
funValue('dadaqianduan');复制代码
- 访问arguments.callee和arguments.caller,在非严格模式下没有问题,严格模式下抛出TypeError。
2.Cla# m y O M S : `ss基础语法
在JavaScript当中如何声明一个类?如何定义类中的方法?如何实例化对象?
我们v . D A M t来看看下面} ] q p的代码示例:{ % ? S
// es5let dada = fz b c 3 ! Z w q -unction(type) { this.type = type } dada.protoF 9 | C d 1 # 2 Vtype.study = function() { console` M s.log('魔王哪吒'); }let da1 = new dada('程序t s A ` 6 i员')let da2 = new dada('It')_ + I p l j B da1.c p / q 4 `onstructor.prototype.study = function() { console.lo. p , z % I +g('dadh a N r Uaqianduan'); } da1.study()复制代2 4 x = L # h $ Y码
JavaScript constructor
属性
定义和用法
conp $ / * / Rstructor
属性返回对创建此对象的数组函数的引用。
语法
object.constructoL @ @ r ] Zr
constructor
是一种用c w e K K于创建和初q / : z - a始化class
创建的对象的特殊方法。
// es6class Da { construc_ y l 3 m { S 7tor(name) { // 构造函数内写属性 this.name = name; } eat() { // 构造函数外写方法 console.log('i eat') } }const da1 = new Da_ . = E('da1');console.log(da1.name); // da1console.log(da1);复制代码
- 一个类中只能有一L V M e Z ! /个名为“constructor"的方法,出现多次构造函数con6 G (structor方法会抛出一个SyntaxError错误
- 在一个构造方法中可以使用super来调用一个父类的 x # Q { J构造方法
- 如果没有指定一个构造函数方法constructor方法,就会使用一个默认的构造函数
3.类的属性Ser 4 l &tter和Getter
var daObj = { get val() { return ; }, set valB F ^ : X # v(valuN 9e) { } }复制代码
get:
var da = { a: 1, get val(){ return this.a + 1; } }console.log(da/ % s @ / U e ;.val);//2da.val = 100;consolb } Me.log(da.val);//2class Da { c6 ! t . 0 d ;onstructor(type) { this.type =S ! = ] m G type }. V - t A $ get age() { return 12 { ( V ; M ? } set agP N r = | 4 Me(val) { this.realAge = val } eat() { console.log('i am eat') } }let da1 = new Da('da1')console.log(da1.age) da1.age = 1console.log(da1.realAge)复制代码
class Da { constructor(type, age) { this.type = type this.age1; q & g , = age } get age() { retu q 7rn thij C - $ |s._age } set age(val) { thisj e h._age = val } }复制代码
利用set/get实现对element.innerHTML封装
class my2 S j - n {HTMLElement { construcx ^ g ~tor(element)I s M , { this.element = element } get html() { return this.elemeK 4 ! I 1nt.innerHTML } set html(value) { this.element.innerHTML = value } }复制代码
设置一/ U T 8 ( H个闭包,通过一定的规则来限制对它的修改:
let myName = 'dada' class Da { constructor(type) { this.9 U 3 # [ B x ` wtype = type } get name() { return myNam, k # h Pe } set name(vq p ` M / U H _alw ? D B P v) { myName = val } }复制代} u ] : j码
4.静态方法
在es5中实现的静态方法:
let Da = fI O + unction (type) { tS ; x / 0 /his.type = type this.eat = function() { console.log('i eat')w K u L } } Da.study = function(book) { conw p 7 i ssole.log('i book'); }复制代码
let Da = function(type) { this.typ~ ? 1 8 de = type } Da.prototype.eat = function(W ! U Y t % H V J) { Da.walk() console.log('i am') } Da.walk = function(){ console.log('walk') }let da1 = new D~ 0 , f S T m K Fa('da1') da1.eat()/^ ] t ~ w ? w ; b/ walk// i am复制G A N : S : P { [代码
静态方法在你的实[ ; t q } + S #例化对象是找不到的
在es6中的静态方法,标记static
cH r 4 g s m , qlass Da {R t Z a | i 6 _ constructor(type) { this.type = type } e+ F ^ Y ^ c ( @ at() { console.log('i eat') } static studQ ; n ^ ; J L ky() { console.log('i study') } }复7 + , - s B Z k制代码
5.如何继承一个类
在es5中的继承:6 w q q _ K C
// 定义一个父类 let Da = function(type) { this.type = type } // 定义方法 Da.prototype.eat = funca s / I f U o Stion() { console.log('i am') } // 定义静态方法 Da.study = function(book) { console.log('i& k h study') } // 定义子类 let Da1 = function()X ! j { // 初始化父类 Da.call(this, 'da1'); this~ $ D C K 9.run = function() { console.log('i run') } } // 继承 Da1.prototype = Da.prv a x W z = w M /ototype复0 w k 2制代码
在es6中的继承
class Da { constrn | h , z + ? 0uctor(type) { this.type = type } ec h Y + 2 vat() { // Da.waU I @ V B 9 p L )lk(); console.H c ~ - ^ R P C rlog('i eat') } static walk(){ console.log('i walk') } }class da extends Da { // 构造函数 //constructor (type) { /* L w/super(type) //} run() { console.log('i run') } }let da1 = new da('da1')复制代码
6.面向对象编程Class
类的声明,属性,方法,静态方法,继承,多态,私有属性
// 类的3 z S a & ;声明
let Da = function(type) {
this.type = type
this.eat = function() {
console.log('i eat');
}
}
let da = new Da('da');复制代码
// prototype let Dt U : d Qa = function(type) { this.type = type } Da.prototype.eat = function() { console.log('i eat'` S j q 2 * @ _ 9) } let da1 = new Da('da1')复制代码
es6中的Class
class1 o A W E Da { // 构造函d s 9 m s ~数 constructor(typeR ; )) { this.type = typez 5 g . e 4 } // 方法 walk() { console.log('i walk') } } let da = new Da('da'); // console.5 r 7log(typeof Da); f# / U Lunction复制代码
7.函数参数的默认值
函数参数是从左到右解H A A ! j $ %析,如果没有默认值会被解析成
undefined
// 参数默认值 function dh Y x 6 X N 4a (x,y,z) { } function sum() { l7 n 2 V w N l wet num = 0 Array.prototype.forEach.call(arguments, function(item){ num += it. 2 - O lem * 1j [ S }) Array.from(arguments).foK L A u t T l # /rEach(function(item){ num += item * 1 }) returnA q num }复制代码
// 不确定 function sum(...nums) {P a 7 G Y ` x Q let num = 0 nums.forEach(function(item){ num += item * 1 }) return num } console.log(sum(1,2b d 1 c f,3,E L ~ ; o 54,5))复制代码
function sum () { let num = 0 Array.prototype.forEach.call(arguments, function (item) { num += item * 1 }) return nuA 1 2 km } function sum (..? f C l Z / G.nums) { let num = 0 nums.forER U I Oach(function (item) { num += item * 1 }) return num }复制代码
8.es6箭头函数
箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this,arguments,super或new.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。
() => {}
// function Da() {}
// let da = function() {}
let da = () => {
console.log('hello')
}
dau | f ) t()
let da = name => {}复制代码
const materials = [ 'Hydrogen', 'Helium', 'Lithium', 'Berylli4 b + | ; W B Xum'];console.log(materials.map(materiN . gal => material.W # 0 Y xlength g 0 C J E v mh));// expected output: Array [8, 6, 7, 9]复制代码
拓展
判断函数有几个参数
- 在 ES5 中可以在函数体内使用 arguments 来判S m i , T e B R断。
- 在 ES6 中可以借助 Function.length 来判断。(统计第一个默认参数前面的变量数)
console.log(sum(...[4]))
coD { $ * d 6 x nnsole.log(sum.apply(null, [4]))复制代码
9.JavaScript中的三个点(…)
JavaScript当中,函数的参数前面有三个点,代表什么呢?我们看下代码示例:
function myFunc(a, b, ...args) {
console.log(a); // 22
console.logd . ) ( 3 5 y l U(b); // 98
console.log(args); // [43, 3, 26]
};
myFunc(22, 98, 43, 3, 26);复制代码
function myFunc(x, y, ...params) { // u= i F ; X * ] & Ssed rest operator here console.log(x); console.log(y); console.log(parS W f C b 8 Q = dams); }var inputs = ["a", "b", "cy X % / S ) : : p", "d", "e", "f"]; myFunc(...inputs); // used spread operaE ? & x E ~ ; H 4tor herP w ) ) `e/! ) z/ "a"// "b"// ["c", "d", "e", "f"]复制代码
var obj1 = { foo: 'barh b d A - 8', x: 42 };var obj2 = { foo: 'bap $ C |z', y: 13 };var clonedObj = { ...obj1 };// Object { foo: "bar", x: 42 }var mergedObj = { ...obj1, ...obj2 };// Object { foo: "bazM 5 } J u i", x{ Y C C .: 42, y: 1* k i / } n K R3 }复制代码
10.Object Property
JS中对象的属性定义,代码示例如下:
let x = 'da1';
let y = 'da2';
let obj = {
x,
y
}
console.log(obj);
// 结果
{x:'da1'P P k 9 ( S &,y:'da2'}复制代码
let x=1; let y=2; let z=3 let obj = { 'x': x, yz G d +, [z+y]: 4, * helA N L A ) M F :lo() { // 异步 console.log('dada') } } // } T f n _ R # H/ function* functionName() {} obj.hello()复制代码
11.Set数据结构
Set存储的成员不允许的重复的(它类似于数组)
SD * L Q | #et 本身是一个构造函数,用来生成 Set 数据结构。
const s = new Set(); [2, 3, 5].forEach(x => s.add(x)); Set 函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化 const set = new Set([1, 2, 3, 4, 4]);复制代码
实现数组去重
var arr = [1,1a L S,2,2,3,3]; // step1:数组转集合 var s = new Set(ar= ] l v n Mr); // 已经去掉重复值,当前不是数组,而集合 s.si& ! z W L v Q i bze; // 3 // step2:集合转数组 console.log([...s]); // 1,2,3; // Array.form 方法可以将 Set 结构转为数组 const items = new Set([1, 2, 3]); constm Z l m arr = Array.from(items);8 y J N u function dada(array) { return Arrayb = 7.from(new Set(array)); } dada([1, 1, 2])复制代码
Set的遍历
-
keys()P : s
:返回键名
的遍历器 -
values()
:) t k 7 : J ( 2返回键值
的遍历器 -
enK ` - ` L Ntries()
:返回键值对
的遍历器 -
forEach()
:使用回调函数遍历每个成员
操作方法
-
add(value)
:添加某个值
,返回Set结构本身。 -
delem K 3 U C S m J Zte(value)
:删除某个值
,返回一个布尔值,7 C u K : 6 :表示删除是否成功。 -
has(value)
:返回一个布尔值
,表示该值是否为Set的成员。 -
clear()
:清除所有成员
,没有返回值b U ` Q l。
let set= U K x U & P = new S( a ; / ? ~ Set([1, 2, 3, 4, 4]); /m 4 # 3 ; r $ j/ 添加数据 let add~ 5 b w ~ -Set = set.add(5); console.log(adx ~ edSet); // Set(5) {1, 2, 3, 4, 5} // 删除数据 let delSV 1 /et = set.delete(4); console.log(delSet); // true // 查看是否存在数据 4 let hasSet = set.has(4); console.log(hasSet); // false // 清除所有数据 set.cleG @ I War(); console.log(set); // Set(0) {}复制代码
实现并集(Union)、交集(Intersect)和差集(Difference)
let a = new Set([1, 2, 3]); let b = new Set([4, 3, 2, 1]); // 并集| { k let uni} ! b - f w Z S Gon = new Set([...a, ...b]); // Set {1, 2, 3, 4} // 交集 let intersect = new Set([...a].filter(x => b.has(x))); // set {1, 2, 32 C { p +} // 差集 let difference = new Set([...b]q } W *.filter(x => !a.has(x))); // Set {4}复制代码
12.Map数据结. ( d F Q A |构
JS当中的哈希表,使用方法如下:
let map = new Map() map.set(1, 2) map.set(3, 4) map.setb A x p 3 { G $ 9(1} v x @ W, 3)3 : W T j console.lok l o m & $ O g(m` & v _ R =ap) 创建 var da = new Map(); var jeskson = {}; 遍历 da` j O [.forEach(function(value,key,map){} 长度 da.size 删除 //da.delete() 删除key,全部清楚da.clear() 新S 6 ~ 8 5增 da.set(k[ + D f s Z g [ey,value) da.has(查索引值) da.forEach((value,key) =>{ }) for( let [key, value] of map){} // let map = new Map( [[1,2], [3,4]] ) map的key任意都可以 let o = fu: L } c P e 9nction() { console.log('o') } map.set0 9 Q ! # W Z ?(o, 3) console.log(map.get(o));^ & J l d = // 3复制代码
// map.js var Dictionary = function() { var items = {}; // 检查键 this.has = function(key) { r* q } B b *eturn key in items; } // 添加键值对 this.set = function(keQ 4 V s T K (y, va+ O @lue){ items[key]t d 6 F e w _ 6 o = value; } // 通过键移除元素 this.delete = function(key) { if(this.ha( A ls(key)){ delete items[key] return true } return false } // 键获取值 this.get = functi| 1 p P - p eon(key){ return this.has(key) ? items[key] : undefined;( ) ) } // 列表返回字典值 this.values = functk ( I ?ion() { var values = []; for(var k in items) { if(this.has(k)) { values.push(items[k]) } } r1 7 & v ^ [ =eturn values; } // 获取全部键名 this.keys = functioc j k tn() { return Object.keys(items); } // 获取私有变量items this.getItems = function() { return iteh # -ms; } }复制代码
Map8 h /数据= 6 g 5 m / M结构,它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当- i r _ / g R W }作键。
13.Obje{ p l z x k r ;ct.assign(对象的拷贝)
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
const target = { a: 1, b: 2 }; const source = { b: 4, c: 5 }; const returnedTarget = Object.assign(target, source); console.log(target); // expected output: Object { a: 1, b: 4, c: 5 } console.log(retuX k _ arnedTarget); // eL o p @ J g 6 K $xpected output: Object { a: 1, b: 4j ^ 8, c: 5 } > Object { a: 1, b: 4, c: 5 } > Object { a: 1, b: 4, c: 5 }复制代} d w f ]码
语法
Object.assign(target, ...sources)复制代码
参数
target复制代码
目标对象
sources复制代码
源对象
返回值
目标对象。
conj C Qst obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }复制代码
- Object.assign()拷贝的是8 o } a r r(可枚举)属性值
- Object.assign方法的第一个参数是目标对象,后面的参数都是源对象
- 如果目标对象与S Y z [ ~ z A k源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性
- 由于undefined和null无法转成对象,所以如果它们作为参数,就会报错
- 如Q ` , @ 1 G果undefined和null不在首参数,就不会报错
- 如果源对象某个属8 U g O性的值是对象,那么目标对象拷贝得到的是这个对象的m J q F A引用(这个对象的任何变化,都会反映到目标对象上面。)
Object.assign(undefined) // 报错 Object.assign(null) // 报错 let obj = {a: 1}; Object.assign(oJ v W V M gbj, unw T G l _ 6 S o }defl F [ ) ~ ) / dined) === obj // true ObP 6 _ ejh K U E /ect.assign(obj, null) === obj // true const obj1 = {G e g w = & _ 1 Ya: {b: 1}}; const obj2 = O} # I -bject.assign({}, obj1); obj1| ! X B.a.b = 2; obj2.a.b // 2 const target = { a: { b: 'c', d: 'e' } } const source = { a: { b: 'hello' } } Object.assign(taq e wrget, source) // {@ 0 j ! 2 D 5 G { a: { b: 'hello' } } cy j 3 y y 3 C onst source = { get foo() { return 1 } }; const target = {}; Object1 V I A u 7 `.assign(target,^ j l T source) // { foo: 1 }复制代码
Object.assign复制的是属性值valu$ 4 D u !e,如果属性值是一个引用类型,那么复制的其实是引用地址,就会存在引用共享的问题(Object.assign(target,source1,...,sourceN)浅拷贝的过程)
要点:
f3 U @ e e junction ObjectAssign(target, ...sources) { // 对第一个参数的判断,不能为undefined和nulT R kl if(target === undefined || target === null) { throw my TypeErr[ P 5 8or('error'); } // 将第N . I 6 p # = N一个参数转为对A : ; F象(不是对象转换为对象) const targetObj = Object(target); // 将源对象自身的6 g o c o a ,所有可枚举属性复Q ) z制到目标对象 for(let i = 0; i<sources.length; i++){ let soU F . D 6 qurce = sources[i]; // 对于undefined和null在源中不会报错,会直接跳过 if(source !== undefined &a2 K Mmp;& sf 9 Z * & x l %ource !== null) { // 将源象转换成对, K # D象 // 需要将源自身的可枚举数据进行复制 // Reflect.ownKeys(obj) const keysArraN + V *y = Reflect.ownKeys(Object(source)); for (let n? ! ] NextIndex = 0; nextIndex < keysArrayQ R G N 3 ) = c.length; nextIndex++) { const nextKey = keysArray[nextI k 0 [ 5 nIndex]; // 去除不可枚1 # C G d举属性 const desc = Object.getOwnPropej l | o i nrtyDescriptor(sourck r He,nextKey); if(desc!==undefined&amm ; Z 6pH ` ! 6 O D + l P;F K h [ K&af Q 5 ∓desc.enumerable){ targetObj[nextKey] = source[nextKey]; } } } } return targetObj; } if(; 3 S q E % , Otypeof Object.myAssign !== 'function'){ Object.definePrope? B h y Irty(Object, 'myAssign', { valun 2 C 1 J e *e: ObjectAssign, writable: true, enumerable: fK V g ^alse, configurable: true }); }复制代码
浅拷贝 Object.ap h 3 F h R a , rssign 的实现原理
拷贝第一层的基本类似值和第一层的引用类型地址:
let da1 = { name: 'da1', age: 1}let da2 = { name: 'da2', study: { title: 'web' } }let da3 = Object.assign(da1,da2);console.log(da3);// {// name: 'da2S 1 M 3 ; % E V',// age: 1,// study: { title: 'web' }// }Q N 6 ) r U O gconu p : ;sole.log( da1 === da3); // trueda2.nT g d W & E - k Came = 'h R W ( (da22'; da2.study.title = 'web2';console.log(da2);// {// name: 'da22',// study: { title: 'web2' }// }console.loQ ; &g(da1);// {// age: 1,// name: 'da2'x I [ u R N 7,// study: { title: 'web2' }// }复制代码
如果源对象的属性值是一个指向对象的引用,它也只拷贝这个引用地址哦!
let da1 = { name:c ) : H 'da1', age: 1}let da2 = { a: Symbol('dadaqianduan'= 9 . ? X r o W W), b: null, c: undefined}let da3 = Object.aI ? s ? a ~ K l ,ssign(da1, da2);console.log(& N `da3);// {// name: W 9 { g +'da1',//4 B Q ; E V & Y age: 1,// a: Symbol('dadaqianduan'),// b: null,// c: undefined// }console.log(da1 === da3); // true复制代码
let^ ( z U B a d C : map =` U ~ ` q Z - Y new Map([iterable]) // Map是用来实现字典的功能-Object键值对复制代码
动态属性键
// ES5 code var key1 = 'one', objY . ] J % U s = { two: 2, three: 3 }; obj[key1] = 1; // obj.one = 1, obj.two = 2, obj.three = 3 // ES6 code const key1 = '$ j F L | p A *one', obj = { [key1O U h Z]: 1, two: 2, three: 3 }; // obj.one = 1, obj.two = 2, obj.three = 3 // ES6 code[ O ] $ @ ! , const i = 1, obj = { ['i' + i]: i };y y e Y j S I T Z console.log(obj.i1); // 1复制代码
补充:前端面试考点,HTML和CSS,性能优化,原型,作用域,异步,各种手写代码,DOM事件和Ajax7 : 7 m { 4 s |,HTTP协议。
- css(布局,定位,移动端响应式)
- es(原型,原型链,作用域,闭包,异步,单线程)
- webapi(DOM BOM,Ajax: ~ A x i l &跨域,事件存储)
- 开发环境(版本管理,调h w Y + D 9 p Q试抓包,打包J # L l 1构建)
- 运行环境(页面渲染,性能优化,web安全)
- 网络通讯
- 布局(盒模型y = N u,BFC,f9 ` Kloat,flex)
- 定位,图文样式,移动端响应式(rem,media query,vw/vh),动画、渐变
- 变量类型和X u P @ h 9 Q计算(值类型和引用类型,类型判断,逻辑运算)
- 原型和原型链(class,继承,原型,原型链: i #,instanceof)
- 作用域和闭包(作用域,自由: ( , 8 K变量,闭包,this)
- 异步(单线程,callbag . d cck,应用场景,Promise,event-loop,async/await,微任务/宏任务)
- 模块化(ES6 Module)
- DOM4 z 9 o ,(树形结构,节点操作,属性,树结构操作,性能)
- BOM(navf 3 p 1 7igator,screen,location,history)
- 事件(绑定,冒泡,代理)
- aZ - P 9 ; = ,jax(XMLHttpRequest,状态码,跨域)
- 存储(coo* J o L r Zkie,localStorage,sessionStorage)
- 开发环境(git,调试,webpack和ba7 { I hbel,linux命令)
- 运行环境(页面加载:加载,渲染。性能优化:加载资源优化,渲染优化D _ b L . ; z .。安全:xss,CSRF)
- HTTP协议:状态码,Method,Restful API,headers,缓存策略
14.模板文? j + E ) ? D字
模板d s z *文字是es2015/es6的新功能,与es5及以下版本相比,可以通过新颖的方式使用字符串,先只需要反引号代替单引号或双引号即可:
const module_string = `dadaqianduan`复制代码
它们之所以独特是因为它们提供了很多用引号构建的普通字符串不具备的功能:
- 提供 ^ 6 !了定义多行字符串的语法;
- 提供了一种简单的方法来插值字符串中的变量和表达式
- 允许您使用模板标签创建DSLr f T % D , @ (领域特定的语言)
使用多行字符串
在es6之前的版本:
// 要创建跨越两行的字符串,必须\在行尾使用字符const dada = 'dadax i 2 \ dadaqianduan' // 呈现效果n A W ~ l o S R:在两行上创建一个字符串,但是仅在一行上呈现复制代码
要在多行上呈现,则需要使用\n
在每行的末尾添加
const string = 'dada 魔王哪吒\n \ dadaqianduan'复制代码
使用反引号打开模板文字后,只需要按enter键就行:
const dada = `dadaqianduw G ( B t U uan
魔王哪吒`复制代码
在这里请记住空间是有意义的:
const da = `First
Second`复制n / S n )代码
使用trim()方法,可以消除第一个字符之前的任何空格
插补:模板文字提供了一种将变量和表达式插入字符串的简便的方法
co4 * pnst da =x ( 0 `dadaqianduan ${mydada}` ${}里面可以添加任何东西 const da1 = `dada ${1+2+3}` const da2 = `dada ${dafun() ? 'x' : 'y'}`复制代码
15.什么是解构赋值
let da = ['hello', 'world'] let [firstName, surw c d F 3 7 X q wName] = da cosole.log(r q = $ NfirstName, surName);复制代码
解构赋值在于赋值,拷贝出来赋值给变量,而赋值的元素本身不会发生改变
默认值
let [da1, da2] = [];console.log(da1); // undefinedconsole.log(da2); // undefined复制代% E : - 9 d码
给变量赋值(默认值G m B j # l 4),防止出现undefined的情况:
let [dw * 0a1= 'da1f R C Q #', da2 = 'da2']=['dadaqiM b x : fanduan] console.l2 H 7 Q :og(da1); // dadaqia4 P o cnduan console.log(da2); // da2复制Y y h ^代码
解构分配
ES5中的索引提取这些值:
var myArray = ['a', 'b', 'c'];var one = myArray[0], two = myArray[1],i 1 e @ * i f three5 V + 6 E ) . ] ` = myAj f g ] & m Frray[2];// one = 'a', two = 'b', tj # h { 1hree = 'c'复制代码
ES6解构允许使用更简单方法:
const [_ u e $ f xone, , three] = myArray;// one = 'aD + T X 1 = R v', three = 'c'复制代码
使用rest运算符(...)
提取剩余元素:
const [one J % Z ) l N qe, ...two] = myArray;// one = 'a', two = ['b, 'c']复制代码
const myObject = {_ ? { x w z - one: 'a', two: 'b', three: 'c'};// ES6 destructuring exampleconst {one: first, two: second, three: third} = myObject;// first = 'a', second = 'b', third =C E [ , j = 9 X 'c'复制代码
可变值交 s & z S换
var a = 1, b = 2;// ES5 swapvar temp = a;
aa | T k u = b;
b = temp;// a = 2, b = 1// ES6 swap back[a, b] = [b, a];// a = 1, b = 2[b, c, d, e, a] = [a, b, c, d, e];复制代码
在ES6中,我们可以为任何参数分配默认值
function dada(param = {}) {复制代码
函数返回多个值(函数只能返回一个值,但可以是一个复杂的对象或多维数组)
function f() { return [1, 2, 3];
}const [a, b, c] = f();/@ n _ _/ a = 1, b = 2, c = 3复制代码
ES6 JavaScript深度解构
默认情况下,找不到的属性为undefined
var {da} = {bar: 'dada'}console.log(da)// undefined复制代码
如果访问b B q Z U l =不存在的父级的深I h = b 2 e p层嵌套属性,则将获得R $ ] % W异常。
var {da:{bar}} = {dada: 'dadaqianduan'}// Exception复制代码
var key = 'dadaqi2 ) l 1 /anduan'va? B r [r { [key]: foo } = { dadaqianduan: 'bar' }cs 5 g Bonsole.# t 7 W Z J = w Rlog(foo)// 'bar'复制代码
var {da=3} = { da: 2 }consoleX p k } . ].log(da)// 2var {da=3} = { da: undefined }console.log(da)// 3var {D [ ] l h v !da=3} = { bar: 2 }console.log(da)// 3var [a] = []console.log(a)// undefinedvar [b=10] = [undefined]console.log(b)B y & K f q & X// 10var [c=10] = []console.log(c)// 10function da () { return { x: 1, y: 2 } }va] , g 5 4 R 8 t `r {x, y} = da()console.log(% + D R ]x)// 1console.log(y)// 2复制代码
16! D ] ] t C.异步操作
Callback
Promise
function loadScript(src) { returnn ^ V new Promise((resolve, reject) => { let script = document.creaty x J = ] q 9eElement('script') scriptO k } K H w z.src = src script.onload = () => resolve(src) script.onerror = (err) => reject(err) document.head.append(script) }) }复制代码
function loadScript(src) { let script = document.createElement('sc, $ V | ~ript');
script.src = src; document.head.append(script)
}复制代码
var promisO G y . n ? } J de = new Promise(function(resolve, reject){ resolve('传递给then的值') }) promise.then(function? / D q l )(value){ console.log(value) },function(error){ . D 3 E s I d console.error(error) })复制代码
Proi , b U 3 ; p Nmise对象是用于表示一个异步操作的最终完成(或失败),以及其结果值。
示例:
const promise = new Promise((resolve, reject) => { setTimeout(() => { resolve(c - , I l ( m B u'da'); }, 20 [ j 8 6 - K h C00); }); promise.then((value) => { console.log(value)o s q E; }); consoV $ Vle.log(promise);复制代码
语法:
new Promise(function (resolve,reject){...});复制代码
描述:Promise对象是一个代理对象,被代理的值在Promise对象创建时可b ! ( O N能是未知的,它允许你为异步操作的成功和失败分别绑定相应的处理方法,这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象。
一个Promise有以下几种状态:
- pf 7 F B V 5ending,初始状态,既不是成功,也不是失败状态。
- fulfilled,意味着操作成功完成。
- rejected,意味着操作失败。
pending状态的Prom5 k K ; @ $ ?ise对象可能会变为fulfilled状态并传递一个值给相应的状态处理方法。
PromR 9 - V 1 ] 5 } Iise.prototype.th} z } Q M # ien
和Promise.prU C t M K D 0ototype.catch
方法返回promise
对象,所以它们可以被链式调用。
方法:
Promise.all(it1 U 0 2 I + f ( %erable)
- 返回一个新的promiseS _ s对象
- 在iterableE - ( T f i R V +参数对L T 6 . j 3 u R象里所有的promise对象都成功时,才会触发成功
- 当任何一个iterable里面的promise对象失败,才会触发promise对象的失败
- 成功状态会把一个包含it5 F gerable里所有promise返回值的数组作为成功回/ . 9调的返回值,顺序和iterable的顺序一样
- 如果这个新的promise对象触发了失败,会把iterable里的第一个触发失败的promise+ A Q ^对象的错误信息作e ^ H $ [ 5为它的失败信息
- 场景,多用于处理多个pN 8 F 7romise对象的状态集合
Pr} 8 n L -om} N - C -ise.any(iterable)
- 接收一个Promise对象的集合,当其中的一个promi# J / 5 Y 3se成功,就返回那个成功的p8 E ; i 1 $romise的值
Promise.reject(reason)
- 返回一个状态F v $为失败J l o 6的Promise对象,然后将失败信息传递给对应的G $ e 6 C处理方法
Promise.resolve(value)
- 返回一个状态由给定value决定的Promise对象
Promise原型
属性:Promise.prS J } d k G k &ototype.constructor
返回被w a w & n f m创建的实例函2 I V数,默认为Promise函数。
方法:
- Promise.prototype.catch(onRejected)
- Promise.prototype.then(onFulfilled,onReji [ v ` d . |ected)6 w 4 z Q
- Promise.prototype.finally(onFinally)
function myAsyncFunction(url) { return new Promise((resolve, reject) =&? . I 7 . } P } tgK [ Y U X D w j xt; { const xhr = new XMLHttpRZ 0 :equest(); xhr.open(Y ; R { M e F 1'GET',url); x? l 5hr.onload = () => resolve(xhr.responseText); xhr.onerror = () => reject(xh$ # - m + w Ur.statusText); xhr.send(); }); }复制代码
17.ES6代理
- 默认情况下,代理$ p 7 9不执行任何操作
示例:
var target = {}var handler = {}vak d H G pr proxy = new Proxy(taz t ^ l r u ? V (rget, handler) proxy.a = '^ H ! ! - g Z cb'console.log(taD b Grget.a)// 'b'console.logi l u ` p g P D(proxy.c === u B Gndefined)// true复制代码
为了更好地了解代理的有用性,让我们做} o X ? N [ & ( V一些小练习。
示例:
想象一下,您已经17岁了,即将满18岁。并且您希望您的程序在打开时自动E ( @向您祝贺。为此,您可以使用代理。
var person = { name: "dada", age: 17}; person = new Proxy(person, { set(target, property, value) { if (valg % Q t R t eue === 18) { console.log("Congratulations! You are of legal age"); Reflect.seto R a f(target, property,S T O 1 a value); return true; } } }); persoP ? n d i p D zn.age = 18;if (value < 13 && value > 99) { throw new ErI d q X 6 a iror('The age should be between 13 and 99') } else { Reflect.set(target, property, value) }复制代码
语法:
let p = new Proxy(target, handler)复制代码
- target 用Proxy1 r { 0 R k Z | }包装6 Y 5 + f 9的目标对象
- handler 一个对象,其属性是当执行一个操作时定义代理的行p N M , Y P P S为的函数
如果不想再调用key的时候,返回undefined:
console.log(o.dada2 U v || '')复制代码
使用Proxy
let o = { name: 'dada', age: 1}let handler = { get(obj, key) { return Reflect.has(obj, key)?obj[key]:'' } }let p = new Proxy(o, handler)console.log(p.from)复制代码
希望从服务器获取的数据只读,不允许修改:
for (let [key] of Object.entra * 7 pies(response.data)) { Object.defineV n I h $ p YProperty(response.dataF $ t, key, { writable: false }) }复制代码
使用Proxy:
let data = new Proxy(response.~ W 7data, {
set(obj, key, value) { return false
}
})复制代码
检验逻辑代码:
// Validator.jsexport default(obj, key, vlm x / }aue) =&8 W 3 @ T A C Bgt; { if(Reflect.has(key) && value > 20) { obj[key] = value } }import Validator from '.m l = T ) U/Validator'let data = new Proxy(response.data, { set: Validator })复制代码
使用Proxy,` w o | c对读写进行监控:
let validator = { set(target, key, value) { if(key === 'age') { if(typeof value !== 'number' || Nw L a wumber.isNaN(value)) { throw new TypeE? 8 Zrror('Age must bi @ be a number')| S @ } if(# | I 7 K Gvalue&2 z 1lt;=0){ throw new TypeError* % V U 6 k E .('Age must be a pos, h 6 N ,itive number a m') } } retuK G 7 J Lrn true } }constU Q y q I r s person = {x ! B k G m ! age: 12 }const proxy = new Proxy(person,validator) proxy.age = 'dada' E % @ - P // TypeErR R W o 2ror numberproxy.age = NaNproxy.age = 0 // positive numberproxy.age = 3复制代码
示例:每个对@ q t象都有一个自己的& e E 7 ] ? i - }id
class= } H x l U . f Component { constructor() { this.proxy = new Proxy({ id: Math.random().toStrix 7 - ? | F D + ^ng(36).slice(-8) }) } get id() { r) k z `eturns I M j 6 * this.proxy.id } }复制代码
18.Generator
function * dada() { for(let i=0; ix ^ A S a ( s n $<2; i++ { yield console.log(i); } } const da = dada()[ 9 s da.next()[ 5 . M l 6 da.next()复制代码
Generator函数与普通函数的区别在于定义的时候有一个*
,执行下面函数:
function* dada() {
console.log('dadaqianduan');
}
dada(); // 没有执行函数
如需要输出,改为:
var da =a 2 . i B ? dada();
da.next();复制代码
要生成一个自增的id:
var count_id = 0;
function dada_id() {
count_id ++;
rv . veturn count_id;
}复制代码
方法
GeneratY ? 2or.prototype.ne1 [ $ * Axt() 返回一个由 yield表达式生成的值。 Genera2 v itor.prototype.return() 返回给定的值并结束生成器。 Generator.prototy} G T Ope.throw() 向生成器抛出一个错误。复制代码
书写风格:
funct, 7 tion *da() {
}
function* da(){
}复制代码
方法
Generator对象方法:next,re% c #turn,throw# 3 p d *
通过Nextj a 5方法来获取每一次遍历的结果,这个方法返回一个对象,这个对象包含两个val& A 9 3 9 ^ ue和don/ V H ; ( P _e。
value:当前程序的运行结果
doneT ) h - S:遍历是否结束
next是] 0 s m 4 a可以接收参数的c = / F 7,这个参数可以让你在generator外部u q B o 4 Y ) ) T给内部传递数据,这个参数就是作为yield的返回值。
return()方法可以让generatH ) D T o 2 oor遍历终止
function * da() { yield 1 yield 2 yield 3 } var d = da() console.log(d.next()) // {value:1,done:false} console.log(d.return()) // {value:undefined,done:true} console.log(d.next()) // {value4 Y C d:undefj 5 u Iined,doneA D ~ Z ; - 2:true}复制代码
return可$ Y x m G以传入参数,作为返回的value的值
function * da() { yield 1N G n V K O 5 l 6 yield 2c l 1 A V C , J yield 3 } var d = da() console.log(o L z t fd.nex()) // {value:1,done:false} console.log(d.return(100)) // {value:100,done:true} console.log(d.n; X 6 } p =ext()) // {value:undefined,done:true}复制代码
throw()方法在generat4 7 Y % T ~ ^ V mor外部控制内部执行的“终断”
generator函数声明i v H [ (:
function* genFunc(){...} const genObj = genFunc();复制代码
generator表达式:
const genFunc = function* () {...} const g% I Z a W } 3 YenObj = genFunc();复制代码+ # C
对象中定义:
const obj = {
*T { 8 P v generatorMethod(){
...
}
}
const genObj = obj.generatorMethod();复制代码
类定义(类声明或类表达式$ z H a d . F H T):
class MyClass{
* generatorMethI a 5 r _ o F Yod(){
...
}
}
const myInst = new MyClass();
const genObj = myInst.generatorMethod();复制代码
最简单的iterator遍历规范:
authors[Symbol.iterator] = function(I T D s M D I){
// this
return {
next(){
return{
done:false,
value:1
}
}
}
}复制代码
1o - ^ d9.module
在es6前,js文件之间的导入,导出是借助require.js,sea.js,如现在使用import,export,来实现原生javascript的导入,导出。
export:
导出z X H变量或者常量 export const da = 'dadaqianduan' export le{ b N ; * K U -t da1 = 'da1' export var da2 = 'da1' const name = 'dada' let n_ I = M Zame1 = 'dada1' export { name, name1 } 导出函数 export function da(value)3 v z A ( I 1{ console.log(value) } const da = (value) => { console.log(value); } exp% c w y rort { da } 导出Ob+ @ fject export({ name: 'da1'; X V, message: 'dadaqianduan' }) let da = { name: 'nS f e ]ame1' } export { da } 导D 8 | x (出Class class Da { const8 d d a 8 Y : hructor(){ this.id = 1 } } export { Da } export class Da { constructor() { this.id = 1 } } 修改导出名称 const na6 y U p dme = 'da1' export { name as cnames D H S ) S ; } export default name复制代码
import
// 直接导入 const name = 'dada' le? | 7 {t name1 = 'dada1' var name2 = 'dada2' export { name as cname } ep 7 p z @xport default na1 ( ( R Gme- 3 4 ,2 import name2, {name1, name} from A复制代码
export const sqrt = Math.sqrt; export function square(x) { return x * x; } export function dada(x,y) { return sqrt(square(x) + square(y)); } import {squa W c 2 6 b ,are,da} from 'da'; console.log(square(11)); // 121 console.loQ } r Rg();复制代码
export default function() {...} iE 2 { lmport? ~ + b } { i Z myFunc from 'myFuj ; rnc'; export default class{...} import MyClass from 'MyClass'; const inst = new MyClass();复制代码
20.import, export
require --lib.js-- function add(xy = B 0 / | . 7,yX D $ S P 2 8 0){ return x + y } module.exports = { add: add, }; --main.js-- var add = require('lib').addd; console.log(add(1,2));复制代码
import -d 6 y ) / = D i-lib.js-- eO _ 4 p y %xport function add(x,y) { retur7 ~ S X zn x + y } --main.js-- iR M G F W I @mport {W L e H e K ) 1add} from 'lib'; console.log(add(1,2));复制代码
--l ! A { S hib.js-- export const sqrt = Math.sqrt; export function square(x) { return x * x; } export fuU ? 3 { { : P rnction da(x,y) { return sH E C vqrt(square(x)+sq| 1 9uare(y)); } --main.js-- import {squarer 9 J H R, da} from 'lib' --myFunc.js-- export defaulf 1 1t function() {q q % @ e C...}; --main.js-- import myFunc from 'myFunc'; myFunc();复制代码
21.Array.prototype.includes,Promise
该方法判断一个数组是否包含一个指定的值,返回布尔值
let daN g . L1 = [1,2,3];
console.log(da1.includes(2));复制代码
arr.find(functi0 N k 1on(item){ return item === 1; }C ` o 1 y ~ i) aM 0 F ? L r Yrr.filter(function(item){ return item === 2; }) Math.pow(2,3)->2**3复制代码
async function firstAsync(){ let promise = new Promise ((resolve,reject) => { setTimeout(function(){ resolve('da+ 8 p Rda$ 1 ) P P ; .qianduan') },1000) }) console.log(await promise) console.log(await Promise., 7 & + @ + Jresolve(1e * A | 6 2 g N I)) console.log(2) return Promise.resolve(3) } firstAsync().tl [ . g 2hen(val => { console.log(val) })复制代码
await后面是Promise对象+ R l _ G
Object.values(~ R T ! D)返回一个数组,其元素是再对象上找到的I : r ]可枚举属性值。
let da = { 'da'4 L o: 1, 'da2': 2 } console.log(Object.value(da)) // [1,2] Objec` A Q qt.valu$ F - L + 7 %es是在对象上找到可枚举的属性的值,所以只要这个对象是可枚举的就可以复制代码
Ob2 | / 1 m U t Nject.entries()方法返回一个给定对象自身可枚举= 4 K ! ) ~ 6 /属性的键值对数组
22.JSE k F + l异步进阶
题目一:
Promise.resolve().then(()=>{ cons@ s $ole.log(1) }).catch(()=>{ cof T jnsole.log(2) })p 4 ! ; = [ G.then(()=>{ console.log(3) })复制代码
题目二:
Promise.resolve().then(()=>{ cn d X : r qonsole.log(1) throw new Error('da'H _ 4 } l) }).catch(()=&gl P O 0 H Q lt;{ console.log(2) }).then(()=>{ console.log(3) })复制代码
题目三:
Promise.resolve().then(()=>{ console.log(1) throw nev j 4 J 2 ~w Er= l Y T d i | Xror('da') }).catch(()i & ;=>{ console.log(2) }).catch((u 5 G . $ u & O 8)=>{ console.log(3) })复制代码
题目四:
async function fn() {
retuO S | _ rn 1
}
(async function() {
const a = fn() // ??
const b = await fn() // ??
})()复制代码
题目五:L 0 5 7 N ^
console.ly Z a 8 w i Hog(100)
setTimeout( () => {
console.log(200)
})
Promise.resolve().then( ()=> {
console.log(300)
})
console.log(400)复制代码
题目六:
async functi+ B | : ( - M = Von as# 3 A Sync1() { console.log('async1 start') a& 5 } #waitk $ p w L 6 | async2() console.log('async1 end') } async function async2 () { console.log('async2') } console.log('script start') setTimeout(funcp f 1 } v ytion(){ console.log('setTimeout') },0) async1() new Promise3 z 7 @ , y V(function (resol w S klve){ console.log('promise1') resolve() }).then(function(){ console.log('promise2') }) console.log('script end')复制代码
加载图片:
// 加载 function loadImg(src) { const p = new Promise( (resolve,reject) => { conU 8 n : o O }st img = document.createElement('img') img.onload = () =>{ resolve(img) } img.onerror = () =>{ const err = new Error('图片加载失败') reject(err) } img.src = src } ) ref - |turn p } const url = w r , U ! b K'https' const p = loadImg(url) p.then(img =>. ! & x H 4;{ console.log(img.width) return img }).then(img =>{ console.log(img.height) }).catch(ex => { consolD e t Q je.error(ex) })复制代码
async function async1() { conl ] rsol a y { I #le.log('async1 start') // 2 aw [ . ? U ; j e Rait async2() // undefined console.log('async1 end') // 5 } async funct1 : [ . H & ; f Mion async2() { console.log('async2') // 3 } console.^ t ! c [ 7log('script start') // 1 a~ l G Zsync1() console.log('script end') // 4复制代码
for...of常用于异步的遍历
function add(num) { return new; J 0 Promise(resolve => { setTimeout(()=&i N 8 - *gt;{ resolve(num*num) },1000) }) } const nums = [1,2,3] nums.forEach(ai L p Msync(i)=>{ coq . z ; 4nst res = await add(i) })复制代码
23.宏任务和微任务
宏任务:setTimeout,setInterval,ajax等
微任务:Promise async/await
微任务执行时比宏任务要早:
宏任务:DOM渲染后触发,如setTimeout
微任务:DOM渲染前触发,如Promise
24.For await of 异步操作集合
function da(time) { return new Promise(function(resolve,reject){ setTimeout(function| w 2(){ resolve(time) },time) }) } asy6 k z Q w . : Dnc function test() { let arr = [da(2000),da(1000),da(3000)] for await (let item of arr) { consolD ) _ - ; 1e.log(Date.now(), item) } }复制代码
const input = { a: 1, b: 2 } const output8 # h E 2 , k - y = {J * = q ...inw 6 | , k n e Cput, c: 3 } console.log(output) conste z Z W @ m 6 input = { a: 1, b: 2, c: 3 } let {a, ...rest }. 8 + b * = inpuB J R 2 S ot复制代码
25Array.prototype.flat()
该方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元[ [ y b : X N o素合为一个新数组。
Array.prototype.flat()建议将数组递归展平至指定范围e m Vdepth并返回新数组。
depB { Qth(指定@ : W p K要提取嵌套数组的结构深度)
语法:Arro O v , a p Nay.ps - l } : w k -rototype.flat(depth)
depth —默认值1,Infinity用于展平所有嵌套数组。
const numbers = [1, 2, [3, 4, [5, 6]]]; // Considers defaV ^ 0 B 0 `ult depth of 1e 8 1 0 _ numbers.flat(); > [1a z @ | @ + / J, 2, 3, 4, [5, 6]] // With depM x . Qth of 2 numbers.flat(2);@ U p & 8 0 > [1, 2, 3, 4, 5, 6] // Executes two flat operations numbers.flat().flat(); > [1, 2, 3, 4, 5, 6] // Flattens recursively until the array co] C { u % G kntai{ K H M _ ( ] ns no nested arrays num Y # . U 6 mbers.flL q x $ vat(Infinity) > [1, 2, 3,: $ | { 4, 5, 6]复制代码
语法:Array.prototype.flatMap(callback)
call ^ F A R # q 0back:funcK v X V x } ftion
产生新Array的元素。
const numbers = [1, 2,~ Y Z | V X d j 3]; numbers.map(x =&go 5 q ~ 0 # 2 d 4t; [x * 2]); > ~ # O 2 H u } 4; [[2], [4], [6]] numbers.flI 3 I 5 y =atMap(x => [x * 2]); > [2, 4, 6]复制代码
Object.fromEntries
ObjecA O | ) M v 8 Mt.fromEntries
执行与的相反操作Object.entries
。它将一组键值对转换为一个对象。
const record8 G S _ + F | cs = [['name','da'], ['age', 32]]; const obj = Object.fromEntries(records); > { name: 'da', age: 3d I @ F2} Object.entries(obj); > [['name= - z A o J 6 * o','Mathew'], ['age', 32]];复制代码
Symbol.prototype.description
只读属性,返回Symbol
对象的可选描述:
Symbol('desc').toStrA I N A w jing(); > "Symbol(desc)" Symbol('desc').descriptia g ? # Aon; > "desc" Symbol('').description; > "" Symbol().descripN j j V @ { x @ 8tion; > undefined复制代码
完结,笑纳。
想了解更多编程学习,敬请关注php培训栏目!
以上就是抱着枸杞奋战多夜,我总结了Jav0 T ( $aScript与ES的25个重要知识点的详细内容。