class
class Foo {
constructor(who){
this.me = who;
}
//给类添加新方法(这些方法都会加在原型prototype上)
identify(){
return "I am " + this.me;
}
}
class Bar extends Foo {
constructor(who){
// super() 指的是调用父类
// 调用的同时,会绑定 this 。
// 如:Foo.call(this, who)
super(who);
}
speak(){
alert( "Hello, " + this.identify() + "." );
}
}
//静态方法可以通过类名调用,不能通过实例对象调用,否则会报错
class Person {
static sum(a, b) {
console.log(a + b)
}
}
var p = new Person()
Person.sum(1, 2) // 3
p.sum(1,2) // TypeError p.sum is not a function
Promise
简介:
Promise是异步编程的一种解决方案,可以替代传统的解决方案--回调函数和事件。ES6统一了用法,并原生提供了Promise对象
1. Promise 的执行流程
new Promise构造器之后,会返回一个promise对象;
为 promise 注册一个事件处理结果的回调函数(resolved)和一个异常处理函数(rejected);
2.Promise 的状态
实例化的 Promise 有三个状态:
Fulfilled: has-resolved, 表示成功解决,这时会调用 onFulfilled.
Rejected: has-rejected, 表示解决失败,此时会调用 onRejected.
Pending: unresolve, 表示待解决,既不是resolve也不是reject的状态。也就是promise对象刚被创建后的初始化状态.
上面我们提到 Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject.
一般用法:
在 ES6 中,可以使用三种办法创建 Promise 实例(对象)
(1). 构造方法
//Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject。
//它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
let promies = new Promise((resolve, reject) => {
resolve(); //异步处理
});
(2). 通过 Promise 实例的方法,调用then 方法返回的也是一个 Promise 对象
promise.then(onFulfilled, onRejected);
(3). 通过 Promise 的静态方法,Promise.resolve(),Promise.reject()
var p = Promise.resolve();
p.then(function(value) {
console.log(value);
});
1.链式调用:
this.getData1(params1).then(res=>{
console.log(res)
return this.getData2(params2)
}).then(res=>{
console.log(res)
})
2.同时传递参数
var p = new Promise(function(resolve, reject) {
resolve();
});
function taskA() {
console.log("Task A");
}
function taskB() {
console.log("Task B");
}
function taskC() {
console.log("Task C");
}
p.then(taskA())
.then(taskB())
.then(taskC())
.catch(function(error) {
console.log(error);
});
3. 同时调用同时结束
//Promise的all方法提供了并行执行异步操作的能力,在all中所有异步操作结束后才执行回调。
Promise.all([p1(params1),p2(params2),p3(params3)]).then(function(data){
console.log(data);
})
4.一个结束都结束
Promise.race()://用法同上all()
asyc/await
acsy:是对函数进行标记为异步,是指不会影响同步函数的执行;
await:其后必须跟着promise对象,作用是等待promise内部回调函数执行完成后结果。
注意:这里的结果是成功的结果。想要获取失败的结果需要用到try...catch...
参数增强
1.为参数添加默认值:
function fun(形参=默认值){
... ...
}
2.剩余参数:
function fun(形参1, 形参2, ...数组名){
}
解构
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错
对象解构
1.基础用法:
const info = {
name: 'cao yuan',
age: 666
};
const { name, age } = node;
console.log(name); // "cao yuan"
console.log(age); // 666
2.添加默认值:
//不添加默认值是为undefine:
//这段代码使用了解构赋值来声明变量name和age,这两个变量分别包含info.name和info.age
//属性的值。name: myName语法的含义是读取名为name的属性并将其值存储在变量myName中。
const info = {
name: 'cao yuan',
age: 666
};
let { name: myName, age: myAge,sex:mySex } = info;
console.log(myName); // "cao yuan"
console.log(myAge); // 666
console.log(mySex); // undefind
//添加默认值:
const info = {
name: 'cao yuan',
};
let { name: myName, age: myAge = 666 } = info;
console.log(myName); // "cao yuan"
console.log(myAge); // 666
//由于info.age属性不存在,变量被默认赋值为666;
3.嵌套对象解构
const info = {
name: 'cao yuan',
age: 666,
child: {
cInfo: {
name: 'cao yuan child',
age: 3,
}
}
};
let { child: { cInfo } } = info;
console.log(cInfo.name); // "cao yuan child"
console.log(cInfo.age); // 3
数组解构
一下可以对比对象解构赋值理解:
解构赋值来声明变量name和age,这两个变量分别包含info.name和info.age属性的值。name: myName语法的含义是读取名为name的属性并将其值存储在变量myName中。
1.基础用法
const colors = [ 'red', 'green', 'blue' ];
const [ firstColor, secondColor ] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"
2.缺省用法
const colors = [ "red", "green", "blue" ];
const [ , , thirdColor ] = colors;
console.log(thirdColor); // "blue"
3.解构赋值:
const colors = [ "red", "green", "blue" ],
firstColor = "black",
secondColor = "purple";
[ firstColor, secondColor ] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"
4.变量交换:
// 在 ES6 中互换值
let a = 1,
b = 2;
[ a, b ] = [ b, a ];
console.log(a); // 2
console.log(b); // 1
5.默认值:
const colors = [ "red" ];
const [ firstColor, secondColor = "green" ] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"
6.嵌套数组解构:
const colors = [ "red", [ "green", "lightgreen" ], "blue" ];
// 随后
const [ firstColor, [ secondColor ] ] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"
7.不定元素:
//(在被解构的数组中,不定元素必须为最后一个条目,在后面继续添加逗号会导致程序抛出语法错误)
//函数具有不定参数,而在数组解构语法中有一个相似的概念——不定元素。在数组中,可以通过...语
//法将数组中的其余元素赋值给一个特定的变量;
const colors = [ "red", "green", "blue" ];
const [ firstColor, ...restColors ] = colors;
console.log(firstColor); // "red"
console.log(restColors.length); // 2
console.log(restColors[0]); // "green"
console.log(restColors[1]); // "blue"
函数传参解构
// options 上的属性表示附加参数
function setCookie(name, value, options) {
options = options || {};
let secure = options.secure,
path = options.path,
domain = options.domain,
expires = options.expires;
// 设置 cookie 的代码
}
// 第三个参数映射到 options
setCookie("type", "js", {
secure: true,
expires: 60000
});
//默认值:
function setCookie(name, value,
{
secure = false,
path = "/",
domain = "example.com",
expires = new Date(Date.now() + 360000000)
} = {}
) {
// ...
}
字符串解构
//字符串也可以解构赋值。这是因为,字符串被转换成了一个类数组的对象;
const [a, b, c, d, e] = 'hello';
console.log(a);//"h"
console.log(b);//"e"
console.log(c);//"l"
console.log(d);//"l"
console.log(e);//"o"
数字或布尔值解构
//解构赋值时,如果等号右边是数值和布尔值,则会先转为对象;
const { toString: s1 } = 123;
console.log(s1 === Number.prototype.toString); // true
const { toString: s2 } = true;
console.log(s2 === Boolean.prototype.toString); // true
数组
常用遍历方法
//1.forEach
myArray.forEach(function (value,index) {
console.log(index+":"+value);
});
//2.every
arr.every((item, index, arr) => {
// item为数组中的元素,index为下标,arr为目标数组
return item > 0; // true
return index == 0; // false
})
//3.some
arr.some((item, index, arr) => {
// item为数组中的元素,index为下标,arr为目标数组
return item > 0; // true
return index == 0; // false
})
//4.map
var arr = [1, 2, 3];
arr.map(item => {
// item为数组的元素
console.log(item);
// 1, 2, 3
return item * 2;
// 返回一个处理过的新数组[2, 4, 6]
})
//5.filter
var arr = [1, 2, 3];
arr.filter(item => {
// item为数组当前的元素
return item > 1;
// [2, 3]
})
//过滤掉值为unfind的
arr.filter(Boolean)
//6.find
//返回第一个符合条件的对象,若没找到返回undefined
arr.find(Boolean)
//7.reduce
arr.reduce(function(prev,now,index,self){
console.log(prev + "--" + now + "--" + index + "--" + (arr == self))
}, 2019)
去重方法
简单数组
//1.利用两层循环+数组的splice方法
function removeDuplicate(arr) {
let len = arr.length
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (arr[i] === arr[j]) {
arr.splice(j, 1)
len-- // 减少循环次数提高性能
j-- // 保证j的值自加后不变
}
}
}
return arr
}
const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN, NaN ]
//2.利用数组的indexOf+forEach方法
function removeDuplicate(arr) {
const newArr = []
arr.forEach(item => {
if (newArr.indexOf(item) === -1) {
newArr.push(item)
}
})
return newArr // 返回一个新数组
}
//3.用数组的includes+forEach方法
const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN, NaN ]
function removeDuplicate(arr) {
const newArr = []
arr.forEach(item => {
if (!newArr.includes(item)) {
newArr.push(item)
}
})
return newArr
}
const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN ]
//4.利用Array.from将Set结构转换成数组
//一般数组去重:利用ES6的set
//Set数据结构,它类似于数组,其成员的值都是唯一的。
function dedupe(array){
return Array.from(new Set(array));
}
dedupe([1,1,2,3]) //[1,2,3]
复杂数组
unique(arr) {
const res = new Map();
return arr.filter((a) => !res.has(a.id) && res.set(a.id, 1))
},
排序
中文排序
// 对象类型中文排序
sortChinese(arr, dataLeven) {
// 参数:arr 排序的数组; dataLeven 数组内的需要比较的元素属性
/* 获取数组元素内需要比较的值 */
function getValue(option) {
// 参数: option 数组元素
if (!dataLeven) return option;
var data = option;
dataLeven.split('.').filter(function (item) {
data = data[item];
});
return data + '';
}
arr.sort(function (item1, item2) {
return getValue(item1).localeCompare(getValue(item2), 'zh-CN');
});
},
冒泡排序
//比较所有相邻元素,如果第一个比第二个大,则交换它们
//一轮下来保证可以找到一个数是最大的
//执行n-1轮,就可以完成排序
//定义一个原生的bubbleSort方法
Array.prototype.bubbleSort = function () {
for(let i = 0; i < this.length - 1; i += 1) {
//通过 this.length 次把第一位放到最后,完成排序
//-i是因为最后的位置是会动态改变的,当完成一次后,最后一位会变成倒数第二位
for(let j = 0; j < this.length - 1 - i; j += 1) {
if(this[j] > this[j+1]) {
const temp = this[j];
this[j] = this[j+1];
this[j+1] = temp;
}
}
}
}
const arr = [4,8,0,1,43,53,22,11,0];
arr.bubbleSort();
console.log(arr);
选择排序
//找到数组中的最小值,选中它并将其放置在第一位
//接着找到第二个最小值,选中它并将其放置到第二位
//执行n-1轮,就可以完成排序
Array.prototype.selectionSort = function() {
for(let i = 0; i < this.length - 1; ++i) {
// 假设最小的值是当前的下标
let indexMin = i;
//遍历剩余长度找到最小下标
for(let j = i; j < this.length; ++j) {
if(this[j] < this[indexMin] ) {
indexMin = j;
}
}
if(indexMin !== i) {
//交换当前下标i与最小下标的值,重复this.length次
const temp = this[i];
this[i] = this[indexMin];
this[indexMin] = temp;
}
}
};
const arr = [5,4,3,2,1];
arr.selectionSort();
console.log(arr);
插入排序
//从第二个数开始往前比
//比它大就往后排
//以此类推进行到最后一个数
Array.prototype.insertionSort = function() {
//从第二个数开始往前比
for(let i = 1; i<this.length; ++i) {
//先把值保存起来
const temp = this[i];
let j = i;
while(j > 0) {
if(this[j-1] > temp) {
this[j] = this[j-1];
} else {
//因为已经是排序过的了,如果比上一位大,那就没必要再跟上上位比较了
break;
}
j -= 1;
}
//这里的j有可能是第0位,也有可能是到了一半停止了
this[j] = temp;
}
};
const arr = [5,4,3,2,1];
arr.insertionSort();
快速排序
//分区: 从数组中任意选择一个基准,所有比基准小的元素放到基准前面,比基准大的元素放到基准的后面
//递归:递归地对基准前后的子数组进行分区
Array.prototype.quickSort = function () {
const rec = (arr) => {
// 预防数组是空的或者只有一个元素, 当所有元素都大于等于基准值就会产生空的数组
if(arr.length === 1 || arr.length === 0) { return arr; }
const left = [];
const right = [];
//以第一个元素作为基准值
const mid = arr[0];
//小于基准值的放左边,大于基准值的放右边
for(let i = 1; i < arr.length; ++i) {
if(arr[i] < mid) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
//递归调用,最后放回数组
return [...rec(left),mid,...rec(right)];
};
const res = rec(this);
res.forEach((n,i) => { this[i] = n; })
}
const arr = [2,3,4,5,3,1];
arr.quickSort();
console.log(arr);
递归数列
//1.兔子数列:
function fib(n) {
if (n === 1 || n === 2) return 1
return fib(n - 2) + fib(n - 1)
}
console.log(fib(3))
//2.使用递归实现深拷贝
//如果拷贝的时候, 将数据的所有引用结构都拷贝一份, 那么数据在内存中独立就是深拷贝(内存隔离,完全独立)
//如果拷贝的时候, 只针对当前对象的属性进行拷贝, 而属性是引用类型这个不考虑, 那就是浅拷贝
function clone(obj){
var temp = {}; //创建一个新对象
for(var key in obj){
if(typeof obj[key] == 'object'){
temp[key] = clone(obj[key]);
}else{
temp[key] = obj[key];
}
}
return temp;
}