标签:win pack 异常 方法 数组去重 安装 war dde typeof
1). 作用域是块级作用域(在ES6之前,js只存在函数作用域以及全局作用域)
if(1){ let a=1; console.log(a) }
2). 不存在变量声明提前;
console.log(b); //ReferenceError: b is not defined let b=2;
3). 不能重复定义
let a=1; let a=2; console.log(a);//Identifier ‘a‘ has already been declared
4). 存在暂时性死区:可以这样来理解
var a=1; if(1){ console.log(a); let a=2; }
① 在一个块级作用域中,变量唯一存在,一旦在块级作用域中用let声明了一个变量,那么这个变量就唯一属于这个块级作用域,不受外部变量的影响;
② 无论在块中的任何地方声明了一个变量,那么在这个块级作用域中,任何使用这个名字的变量都是指这个变量,无论外部是否有其他同名的全局变量;
③ 暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
④ 暂时性死区的意义:让我们标准化代码。将所有的变量的声明放在作用域的最开始。
2. const
const一般用来声明常量,且声明的常量是不允许改变的,只读属性,因此就要在声明的同时赋值。const与let一样,都是块级作用域,存在暂时性死区,不存在变量声明提前,不允许重复定义
const A=1;//重新给常量A赋值会报错 A=3;// Uncaught TypeError: Assignment to constant variable. //错误:赋值给常量
//解构赋值,两边格式要一致 let [a,b,c] = [1,2,3];let [a,[b,c]] = [1,[2,3]]; //交互数据 let a = 10; let b = 20; [a,b] = [b,a];
用class关键字定义对象类型,用extends关键字实现继承
const private2 = Symbol(‘I am symbol value‘) class A { a1 = ‘1‘ // ES7 实例属性,需要new实例来访问, ES6规定class没有静态属性,只有静态方法所以只能在constructor中定义属性 static a2 = ‘2‘ // ES7的静态属性,直接 A.a2 访问,不需要new实例 getA1() { return this.a1 // this指向new实例 } static getA2() { return ‘2’ // 静态方法 } constructor(name) { //一定要有构造方法,如果没有默认生成空构造方法 this.a3 = ‘3‘ // 这里定义实例属性 this.name = name } // 私有方法写法 publicMethod() { private1() // 私有方法1,可以写在class体外 private2() // 利用Symbol值来定义 } [private2]() { // 这里是私有方法 } } const private1 = function() { // 这里也是私有方法,但别export出去} // 最后export class export default A // 通过extends继承 class B extends A{ constructor() { // 一定要在构造函数的第一句调用super super() // 这是调用父类的构造方法 this.b1 = ‘11‘ this.b2 = super.a1 // super直接调用时指向父类构造方法,范围属性时,指向父类实例,或调用父类静态方法 } }
Promise是JS异步编程中的重要概念,异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一。
const request = url => { return new Promise((resolve, reject) => { $.get(url, data => { resolve(data) }); }) }; // 请求data1 request(url).then(data1 => { return request(data1.url); }).then(data2 => { return request(data2.url); }).then(data3 => { console.log(data3); }).catch(err => throw new Error(err));
const promise = new Promise((resolve, reject) => { // 异步处理 // 处理结束后、调用resolve 或 reject });
promise的三种状态
①promise 对象初始化状态为 pending
②当调用resolve(成功),会由pending => fulfilled
③当调用reject(失败),会由pending => rejected
注意:promsie状态 只能由 pending => fulfilled/rejected, 一旦修改就不能再变
1)then方法注册 当resolve(成功)/reject(失败)的回调函数,then方法是异步执行的
// onFulfilled 是用来接收promise成功的值 // onRejected 是用来接收promise失败的原因 promise.then(onFulfilled, onRejected);
2)resolve(成功) onFulfilled会被调用
const promise = new Promise((resolve, reject) => { resolve(‘fulfilled‘); // 状态由 pending => fulfilled }); promise.then(result => { // onFulfilled console.log(result); // ‘fulfilled‘ }, reason => { // onRejected 不会被调用 })
3)reject(失败) onRejected会被调用
const promise = new Promise((resolve, reject) => { reject(‘rejected‘); // 状态由 pending => rejected }); promise.then(result => { // onFulfilled 不会被调用 }, reason => { // onRejected console.log(rejected); // ‘rejected‘ })
4)promise.catch
在链式写法中可以捕获前面then中发送的异常
promise.catch(onRejected) 相当于 promise.then(null, onRrejected); // 注意 // onRejected 不能捕获当前onFulfilled中的异常 promise.then(onFulfilled, onRrejected); // 可以写成: promise.then(onFulfilled) .catch(onRrejected);
promise.then方法每次调用 都返回一个新的promise对象 所以可以链式写法
function taskA() { console.log("Task A"); } function taskB() { console.log("Task B"); } function onRejected(error) { console.log("Catch Error: A or B", error); } var promise = Promise.resolve(); promise .then(taskA) .then(taskB) .catch(onRejected) // 捕获前面then方法中的异常
1)Promise.resolve 返回一个fulfilled状态的promise对象
Promise.resolve(‘hello‘).then(function(value){ console.log(value); }); Promise.resolve(‘hello‘); // 相当于 const promise = new Promise(resolve => { resolve(‘hello‘); });
2)Promise.reject 返回一个rejected状态的promise对象
Promise.reject(24); new Promise((resolve, reject) => { reject(24); });
3)Promise.all 接收一个promise对象数组为参数
只有全部为resolve才会调用 通常会用来处理 多个并行异步操作
const p1 = new Promise((resolve, reject) => { resolve(1); }); const p2 = new Promise((resolve, reject) => { resolve(2); }); const p3 = new Promise((resolve, reject) => { reject(3); }); Promise.all([p1, p2, p3]).then(data => { console.log(data); // [1, 2, 3] 结果顺序和promise实例数组顺序是一致的 }, err => { console.log(err); });
4)Promise.race 接收一个promise对象数组为参数
Promise.race 只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理
function timerPromisefy(delay) { return new Promise(function (resolve, reject) { setTimeout(function () { resolve(delay); }, delay); }); } var startDate = Date.now(); Promise.race([ timerPromisefy(10), timerPromisefy(20), timerPromisefy(30) ]).then(function (values) { console.log(values); // 10 });
/** * 摘自https://www.cnblogs.com/minigrasshopper/p/9141307.html * Promise类实现原理 * 构造函数传入一个function,有两个参数,resolve:成功回调; reject:失败回调 * state: 状态存储 [PENDING-进行中 RESOLVED-成功 REJECTED-失败] * doneList: 成功处理函数列表 * failList: 失败处理函数列表 * done: 注册成功处理函数 * fail: 注册失败处理函数 * then: 同时注册成功和失败处理函数 * always: 一个处理函数注册到成功和失败 * resolve: 更新state为:RESOLVED,并且执行成功处理队列 * reject: 更新state为:REJECTED,并且执行失败处理队列 **/ class PromiseNew { constructor(fn) { this.state = ‘PENDING‘; this.doneList = []; this.failList = []; fn(this.resolve.bind(this), this.reject.bind(this)); } // 注册成功处理函数 done(handle) { if (typeof handle === ‘function‘) { this.doneList.push(handle); } else { throw new Error(‘缺少回调函数‘); } return this; } // 注册失败处理函数 fail(handle) { if (typeof handle === ‘function‘) { this.failList.push(handle); } else { throw new Error(‘缺少回调函数‘); } return this; } // 同时注册成功和失败处理函数 then(success, fail) { this.done(success || function () { }).fail(fail || function () { }); return this; } // 一个处理函数注册到成功和失败 always(handle) { this.done(handle || function () { }).fail(handle || function () { }); return this; } // 更新state为:RESOLVED,并且执行成功处理队列 resolve() { this.state = ‘RESOLVED‘; let args = Array.prototype.slice.call(arguments); setTimeout(function () { this.doneList.forEach((item, key, arr) => { item.apply(null, args); arr.shift(); }); }.bind(this), 200); } // 更新state为:REJECTED,并且执行失败处理队列 reject() { this.state = ‘REJECTED‘; let args = Array.prototype.slice.call(arguments); setTimeout(function () { this.failList.forEach((item, key, arr) => { item.apply(null, args); arr.shift(); }); }.bind(this), 200); } } // 下面一波骚操作 new PromiseNew((resolve, reject) => { resolve(‘hello world‘); // reject(‘you are err‘); }).done((res) => { console.log(res); }).fail((res) => { console.log(res); })
使用Generator
可以很方便的帮助我们建立一个处理Promise
的解释器;
async
/await
这样的语法,可以让我们以接近编写同步代码的方式来编写异步代码(无需使用.then()
或者回调函数)
Generator
是一个函数,可以在函数内部通过yield
返回一个值(此时,Generator
函数的执行会暂定,直到下次触发.next()
) 创建一个Generator
函数的方法是在function
关键字后添加*
标识。
在调用一个Generator
函数后,并不会立即执行其中的代码,函数会返回一个Generator
对象,通过调用对象的next
函数,可以获得yield
/return
的返回值。 无论是触发了yield
还是return
,next()
函数总会返回一个带有value
和done
属性的对象。 value
为返回值,done
则是一个Boolean
对象,用来标识Generator
是否还能继续提供返回值。 P.S. Generator
函数的执行时惰性的,yield
后的代码只在触发next
时才会执行。
function * oddGenerator () { yield 1 yield 3 return 5 } let iterator = oddGenerator() let first = iterator.next() // { value: 1, done: false } let second = iterator.next() // { value: 3, done: false } let third = iterator.next() // { value: 5, done: true }
function getRandom () { return new Promise(resolve => { setTimeout(_ => resolve(Math.random() * 10 | 0), 1000) }) } async function main () { let num1 = await getRandom() let num2 = await getRandom() return num1 + num2 } console.log(`got data: ${await main()}`)
Async函数始终返回一个Promise
async function throwError () { throw new Error() } async function returnNumber () { return 1 } console.log(returnNumber() instanceof Promise) // true console.log(throwError() instanceof Promise) // true
Await是按照顺序执行的,并不能并行执行,JavaScript
是单线程的,这就意味着await
一只能一次处理一个,如果你有多个Promise
需要处理,则就意味着,你要等到前一个Promise
处理完成才能进行下一个的处理,这就意味着,如果我们同时发送大量的请求,这样处理就会非常慢。
function delay () { return new Promise(resolve => setTimeout(resolve, 1000)) } let tasks = [1, 2, 3, 4] //要4s才能执行完 async function runner (tasks) { for (let task of tasks) { await delay() } } //优化,缩短执行时间 async function runner (tasks) { tasks = tasks.map(delay) await Promise.all(tasks) } console.time(‘runner‘) await runner(tasks) console.timeEnd(‘runner‘)
Generator
与async function
都是返回一个特定类型的对象:
Generator
: 一个类似{ value: XXX, done: true }
这样结构的Object
Async
: 始终返回一个Promise
,使用await
或者.then()
来获取返回值Generator
是属于生成器,一种特殊的迭代器,用来解决异步回调问题感觉有些不务正业了。。 而async
则是为了更简洁的使用Promise
而提出的语法,相比Generator + co
这种的实现方式,更为专注,生来就是为了处理异步编程。
// 两个参数: (x, y) => x * x + y * y // 无参数: () => 3.14 // 可变参数: (x, y, ...rest) => { var i, sum = x + y; for (i=0; i<rest.length; i++) { sum += rest[i]; } return sum; }
var obj = { age: 1, say: function() { setTimeout(function() { console.log(this, this.age); // window undefined }, 0); }, } var obj1 = { age: 1, say: function() { setTimeout(() => { console.log(this, this.age); // obj1 1 }, 0); } };
这里可以看出箭头函数中访问的this实际上是其父级作用域中的this,箭头函数本身的this是不存在的,这样就相当于箭头函数的this是在声明的时候就确定了(即this
总是指向词法作用域,也就是外层调用者handler),这个特性是很有用的,所以,用call()
或者apply()
调用箭头函数时,无法对this
进行绑定,即传入的第一个参数被忽略。
var handler = { id: ‘111‘, doSomething: function(e) { console.log(e); }, init: function() { document.addEventListener(‘click‘, (event) => { // 这里绑定事件,函数this就可以访问到handler的方法doSomething this.doSomething(event); }, false); } } handler.init();
var Person = (name) => { // Uncaught TypeError: Person is not a constructor this.name = name; } var person = new Person(‘Jack‘);
var foo = (val) => { console.log(arguments); // Uncaught ReferenceError: arguments is not defined }; foo(); //这个特性也很好测试,但是实在要使用arguments对象要怎么办呢?我们可以使用es6的另一个新特性rest参数,完美替代 var foo = (...args) => { console.log(args); // [1, 2, 3] }; foo(1, 2, 3);
JavaScript的默认对象表示方式{}
可以视为其他语言中的Map
或Dictionary
的数据结构,即一组键值对。但是JavaScript的对象有个小问题,就是键必须是字符串。但实际上Number或者其他数据类型作为键也是非常合理的。为了解决这个问题,最新的ES6规范引入了新的数据类型Map。
Map的遍历:
var m = new Map([[‘Michael‘, 95], [‘Bob‘, 75], [‘Tracy‘, 85]]); m.get(‘Michael‘); // 95 //初始化Map需要一个二维数组,或者直接初始化一个空Map。Map具有以下方法: var m = new Map(); // 空Map m.set(‘Adam‘, 67); // 添加新的key-value m.set(‘Bob‘, 59); m.has(‘Adam‘); // 是否存在key ‘Adam‘: true m.get(‘Adam‘); // 67 m.delete(‘Adam‘); // 删除key ‘Adam‘ m.get(‘Adam‘); // undefined //由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉 //遍历Map var m = new Map([[1, ‘x‘], [2, ‘y‘], [3, ‘z‘]]); m.forEach(function (value, key, map) { console.log(value); });
Set
和Map
类似,也是一组key
的集合,但不存储value
。由于key
不能重复,所以,在Set
中,没有重复的key。
//要创建一个Set,需要提供一个Array作为输入,或者直接创建一个空Set: var s1 = new Set(); // 空Set var s2 = new Set([1, 2, 3]); // 含1, 2, 3 //重复元素在Set中自动被过滤: var s = new Set([1, 2, 3, 3, ‘3‘]); s; // Set {1, 2, 3, "3"} //通过add(key)方法可以添加元素到Set中,可以重复添加,但不会有效果: s.add(4); s; // Set {1, 2, 3, 4} s.add(4); s; // 仍然是 Set {1, 2, 3, 4} //通过delete(key)方法可以删除元素: var s = new Set([1, 2, 3]); s; // Set {1, 2, 3} s.delete(3); s; // Set {1, 2} //遍历Set var s = new Set([‘A‘, ‘B‘, ‘C‘]); s.forEach(function (element, sameElement, set) { console.log(element); });
数组去重
//1.for循环嵌套,利用splice去重 function newArr(arr){ for(var i=0;i<arr.length;i++){ for(var j=i+1;j<arr.length;j++) if(arr[i]==arr[j]){ //如果第一个等于第二个,splice方法删除第二个 arr.splice(j,1); j--; } } } return arr; } var arr = [1,1,2,5,6,3,5,5,6,8,9,8]; console.log(newArr(arr)) //2.建新数组,利用indexOf去重 function newArr(array){ //一个新的数组 var arrs = []; //遍历当前数组 for(var i = 0; i < array.length; i++){ //如果临时数组里没有当前数组的当前值,则把当前值push到新数组里面 if (arrs.indexOf(array[i]) == -1){ arrs.push(array[i]) }; } return arrs; } var arr = [1,1,2,5,5,6,8,9,8]; console.log(newArr(arr)) //3.ES6中利用Set去重 function newArr(arr){ return Array.from(new Set(arr)) } var arr = [1,1,2,9,6,9,6,3,1,4,5]; console.log(newArr(arr))
现在的Chrome浏览器已经支持ES6了,但是有些低版本的浏览器还是不支持ES6的语法,这就需要我们把ES6的语法自动的转变成ES5的语法。Webpack是有自动编译转换能力的,除了Webpack自动编译,还可以使用用Babel来完成。
{ "name": "es6", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
可以根据自己的需要进行修改,比如我们修改name的值为es6。
{ "presets":[ "es2015" ], "plugins":[] }
这个文件我们建立完成后,现在可以在终端输入的转换命令了,这次ES6成功转化为ES5的语法。 babel dist/index.js -o src/index.js
{ "name": "es6", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "babel src/index.js -o dist/index.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-cli": "^6.24.1", "babel-preset-es2015": "^6.24.1" } }
修改好后,以后我们就可以使用 npm run build 来进行转换了。
webpack的loaders是一块很重要的组成部分。我们都知道webpack是用于资源打包的,里面的所有资源都是“模块”,内部实现了对模块资源进行加载的机制。但是Webpack本身只能处理 js模块,如果要处理其他类型的文件,就需要使用 loader 进行转换。
Loader 可以理解为是模块和资源的转换器,它本身是一个函数,接受源文件作为参数,返回转换的结果,例如可以使用loader加载器可以快速编译预处理器(less,sass,coffeeScript)。 Loader 可以在require()引用模块的时候添加,也可以在 webpack 全局配置中进行绑定,还可以通过命令行的方式使用。
loader的特性是:
//摘自博客:https://blog.csdn.net/qq_42149830/article/details/88295747 function _defineProperties(target,prop){ prop.forEach(ele => { //可能会传入多个属性 Object.defineProperty(target,ele.key,{ value:ele.value, writable:true, configurable:true, }) });//设置所设置的属性是否可写,可枚举 } function _createClass(_constructor,_prototypeProperties,_staticProperties){ //这里传入的三个参数分别是构造函数,原型上的属性,静态属性 if(_prototypeProperties){ //设置公有属性 _defineProperties(_constructor.prototype,_prototypeProperties) } if(_staticProperties){ //设置静态属性 _defineProperties(_constructor,_staticProperties) } } function _classCallCheck(_this,_constructor){ if(!(_this instanceof _constructor)){ //判断是否是通过new(创建实例)来调用_constructor throw "TypeError: Class constructor AirPlane cannot be invoked without ‘new‘" } } var FatherPlane=(function(){ function FatherPlane(name,color){ _classCallCheck(this,FatherPlane) this.name=name||‘liu‘; this.color=color||‘red‘ } _createClass(FatherPlane,[ { key:‘fly‘, value:function(){ console.log(‘fly‘) } } ],[ { key:‘static‘, value:function(){ console.log(‘static‘) } } ]) return FatherPlane; })() var airplane=new FatherPlane()
标签:win pack 异常 方法 数组去重 安装 war dde typeof
原文地址:https://www.cnblogs.com/lxy-starry/p/11239376.html