js方法文档
1.类和对象
类中属性和方法
// 1.创建类class 创建一个明星类习惯定义首字母大写
class Star {
// 类的共有属性放到constructor里面
constructor(uname, age) {
this.uname = uname;
this.age = age;
}
sing(song) {
console.log(this.uname + '唱' + song);
}
}
// 2.利用类创建对象new
var ldh = new Star('刘德华', 21);
ldh.sing('冰雨');
console.log(ldh);
// 类里面有个constructor函数,可以结束参数,同时返回实例对象
// constructor函数只要new生成实例时,就会自动调用这个函数,如果我们不写,类也会自动生成这个函数
// 类名后面不加小括号
</script>
类的继承
可以继承类里面的属性和方法,就近原则
类里面的共有的属性和方法一定要加this使用
- super继承属性
class Father {
constructor(x, y) {
this.x = x;
this.y = y;
}
sum() {
console.log(this.x + this.y);
}
}
// 属性和方法都可以继承
class Son extends Father {
constructor(x, y) {
//调用了父类中的构造函数,否则就传给子类会报错,因为用的是父类的this
super(x, y);
}
}
var son = new Son(2, 5);
var son1 = new Son(11, 23);
son.sum()
son1.sum()
</script>
-
super继承方法
1.继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,有就执行子类
2.如果子类没有,就去找父类,如果父类有,就执行父类的这个方法
class Father { say() { return '天龙' } } class Son extends Father { say() { // console.log('八部'); console.log(super.say() + '八部');//天龙八部 } } var son = new Son();
-
子类继承同时扩展自己
class Father { constructor(x, y) { this.x = x; this.y = y; } sum() { console.log(this.x + this.y); } } // 属性和方法都可以继承 class Son extends Father { constructor(x, y) { // 子类在构造函数中使用super必须放到this前面 super(x, y); this.x = x; this.y = y; } subtract() { console.log(this.x - this.y); } } var son = new Son(9, 5); son.subtract(); son.sum();
类的注意事项
<button>点击</button>
<script>
var that;
class Star {
constructor(uname, age) {
// constructor里面的this指向的是创建的实例对象
// 类里面的共有属性和方法一定要加this使用
that = this;
this.uname = uname;
this.age = age;
// this.sing()
this.btn = document.querySelector('button');
// 不要加(),否则就直接调用了,
this.btn.onclick = this.sing;
}
sing() {
// 这里是btn调用,所以函数this是btn
// console.log(this.uname);//undefined
console.log(that.uname);
}
}
var ldh = new Star('刘德华');
// es6中类没有变量提升,所以必须先定义类,才能通过类实例化对象
</script>
</body>
2.构造函数和原型
原型对象prototype
//每个构造函数都有一个prototype属性对象,这个对象的所有属性和方法都会被构造函数所有
function Star(uname, age) {
this.uname = uname;
this.age = age;
// this.sing=function(){
// console.log('我会唱歌');
// }
/* 原型是对象,prototype为原型对象
方法为复杂数据类型会开辟新的内存空间
原型的作用是共享方法,减少资源消耗*/
Star.prototype.sing = function () {
console.log('我会唱歌');
}
}
var ldh = new Star('刘德华', 15);
var zxy = new Star('张学友', 19);
// 一般情况下,我们公共属性定义到构造函数里面,公共方法则定义到原型对象上
console.log(ldh.sing === zxy.sing);//true
对象原型__proto__
<script>
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
Star.prototype.sing = function () {
console.log('我会唱歌');
}
var ldh = new Star('刘德华', 18);
var zxy = new Star('张学友', 19);
ldh.sing();
console.log(ldh);//对象身上系统自己添加一个__proto__指向我们构造函数的原型对象prototype
console.log(ldh.__proto__ === Star.prototype);//true
// 方法的查找规则:首先看ldh 对象身上是否有sing方法,如果有就执行这个对象上的sing
//如果没有sing这个方法,因为有__proto__的存在,就去构造函数原型对象prototype身上去查找sing这个方法
</script>
原型constructor
原型对象和对象原型都带ru有一个指向原来构造函数的constructor
function Star(uname, age) {
this.uname = uname;
this.age = age;
// Star.prototype.sing = function () {
// console.log('我会唱歌');
// },
// Star.prototype.movie = function () {
// console.log('我会演电影');
// }
};
// 很多情况下,我们需要手动的利用constructor这个属性指回原来的构造函数
Star.prototype = {
// 如果不加就指向一个对象了
constructor: Star,
sing: function () {
console.log('我会唱歌');
},
movie: function () {
console.log('我会演电影');
}
}
var ldh = new Star('刘德华', 18);
var zxy = new Star('张学友', 19);
console.log(Star.prototype);
console.log(ldh.__proto__);
// 原型对象和对象原型都带有一个指向原来构造函数的constructor
// console.log(Star.prototype.constructor);
// console.log(ldh.__proto__.constructor);
原型链(就近原则)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D6YXW5LC-1668090175085)(C:\Users\林威\Desktop\原型链简易版.jpg)]
原型链对象查找机制及this指向
function Star(uname, age) {
this.uname = uname;
this.age = age;
// 在构造函数中,里面this指向的是对象实例ldh
console.log(this);
}
Star.prototype.sing = function () {
console.log('我会唱歌');
// 原型对象函数里面的this指向的也是实例对象ldh
console.log(this);
}
var ldh = new Star('刘德华', 18);
// 按原型链就近原则查找
ldh.sex = '女';
// Star.prototype.sex = '男';
Object.prototype.sex = '男'
console.log(ldh.sex);//女
call方法
call(),也可以调用函数,调用这个函数,并且修改函数运行时的this指向
-
fun.call(thisArg,a1,a2)
-
thisArg:当前调用函数this的指向对象
-
a1,a2:传递的其他参数
-
借用父构造函数继承属性
// 借用父构造函数继承属性 function Father(uname, age) { this.uname = uname; this.age = age; } function Son(uname, age, score) { // this 指向子构造函数的对象实例 Father.call(this, uname, age); this.score = score } var son = new Son('刘德华', 13, 99); console.log(son);
3.原型对象继承方法
<script>
function Father(uname, age) {
this.uname = uname;
this.age = age;
};
Father.prototype.money = function () {
console.log('我要赚钱');
}
function Son(uname, age) {
Father.call(this, uname, age)
}
// Son.prototype=Father.prototype这样有问题,如果修改了子原型对象,父原型对象会跟着要求变化
Son.prototype = new Father();
Son.prototype.constructor = Son;
Son.prototype.exam = function () {
console.log('孩子要考试');
}
var son = new Son('dad', 45);
console.log(son);
console.log(Father.prototype);
</script>
4.ES5新增数组方法
3个参数(当前项的值,当前的索引,数组对象本身)
forEach遍历
<script>
var arr = [1, 2, 3];
var sum = 0;
arr.forEach(function (a, b, c) {
console.log('数组元素' + a);
console.log('数组索引号' + b);
console.log('数组本身' + c);
sum += a;
})
console.log(sum);//6
filter筛选
// ilter筛选数组,返回一个新的数组1
var arr = [12, 33, 44, 66, 3, 7]
var newArr = arr.filter(function (value, index, total) {
// return value % 2 === 0;
return value >= 20
})
console.log(newArr);
</script>
some✴️
检测数组中的元素是否满足指定条件,返回的是布尔值,如果查到就返回true,否则false
如果找到第一个满足条件的元素,则终止循环,不在继续查找;
要终止循环return后面一定要加turn
var arr = [10, 24, 4];
var flag = arr.some(function (value) {
return value > 20
})
console.log(flag);//true
var arr1 = ['red', 'pink', 'green'];
var flag1 = arr1.some(function (value) {
return value === 'pink';
})
console.log(flag1);//true
find
方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
var ary = [{
id: 1,
name: '张三'
}, {
id: 2,
name: '李四'
}];
// 如果查找不到就返回undefind
let target = ary.find(item => item.id===2);
console.log(target)
findIndex
let ary = [10, 20, 50];
// 用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1
let index = ary.findIndex(item => item > 15);
console.log(index);//1
includes
includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回
true
,否则返回false
。
const array1 = [1, 2, 3];
console.log(array1.includes(2));
// expected output: true
const pets = ['cat', 'dog', 'bat'];
console.log(pets.includes('cat'));
// expected output: true
console.log(pets.includes('at'));
// expected output: false
flat
看上面文档
flatmap
reduce
计算数组所有元素的总和
// 注意:如果设置初始值,那么在第一次调用回调函数时,prev的值为这个初始值,如果不设置初始值,那么默认情况下,prev的值为数组的第一个元素
var a = [1, 2, 3]
var b = a.reduce(function (h, f) {
return h + f
}, 5)//5+1+2+3
console.log(b);//11
------------------------------------------------
//返回未被选中的
undoneLength() {
return state.list.reduce((pre, item) => {
return pre + (item.done === true ? 0 : 1)
}, 0)
},
join
数组转为字符串
5.字符串方法
trim
trim(),去除字符串两侧空格,返回一个新的字符串
var str = ' an dy ';
console.log(str);
var str1 = str.trim();
console.log(str1);
startsWith()和endsWith()
-
startsWith():表示参数字符串是否在字符串的头部,返回布尔值
-
endsWith():表示参数字符串是否在字符串的尾部,返回布尔值
let str = 'Hellow word'; str = str.startsWith('He'); console.log(str);
repeat
// repeat方法表示将原字符串重复n次,返回一个新字符串
console.log("y".repeat(5))
split
字符串转为数组
6.Object.defineProperty()
object.defineProperty(obj,prop,descriptor)
只有用这个方法加进去的才受控制
-
obj:必需。目标对象
-
prop:必需。需定义或修改的属性的名字
-
descriptor:必需。目标属性所拥有的特性
- value:设置属性的值
- writable:值是否可以重写修改。true/false,默认为false
- enumerable:目标属性是否可以被枚举。true/false,默认为false
- configurable:目标属性是否可以被删除或是否可以再次修改特性true/false,默认为false
- 这里id是本身有的,所以不受控制
var obj = { id: 1, pname: '小米', price: 1999 }; // 有则修改,无则添加 Object.defineProperty(obj, 'num', { value: 1000, // 因为writable默认为false }); obj.num = 3; obj.id = 3; console.log(obj);//id:3,num:1000
7.函数
函数定义方式
// 函数的定义方式
// 1.自定义函数(命名函数)
function fn() { }
// 2.函数表达式(匿名函数)
var fun = function () { };
// 3.利用 new Function('参数1','参数2','函数3');
// 了解就好,效率较低
var f = new Function('a', 'b', 'console.log(a+b)');
f(1, 2);
// 4.所有函数都是 Function 的实例(对象)
console.dir(f);
// 5.函数也属于对象
console.log(f instanceof Object);
this指向
调用方式 | this指向 |
---|---|
普通函数调用 | window |
构造函数调用 | 实例对象,原型对象里面的方法也指向实例对象 |
对象方法调用 | 该方法所属对象 |
事件绑定方法 | 绑定事件对象 |
定时器函数 | window |
立即执行函数 | window |
apply方法
// 改变函数内this指向 js 提供了3种方法 call() apply() bind()
// 2.apply() 应用 运用的意思
var o = {
name: 'andy'
};
function fn(arr) {
console.log(this);
console.log(arr);//'red'
};
fn.apply(o, ['red']);
// 1.也是调用函数 第2跟可以改变函数内部的this指向
// 2.但是他的参数必须是数组,也可以是伪数组
// 3.apply 的主要应用 比如说我们可以利用 apply 借助于数学内置对象求最大值
// Math.max()
var arr = [1, 66, 3, 99, 4];
var max = Math.max.apply(Math, arr);
var min = Math.min.apply(Math, arr);
console.log(max,min);
bind方法⭐️
var o = {
name: 'andy',
}
function fn(a, b) {
console.log(a + b);
console.log(this);
}
// 改变this的同时不会直接调用,而是返回一个新的函数
var f = fn.bind(o, 2, 4);
f();
应用场景函数内部的this指向
都可以改变
-
call经常做继承·
-
apply经常和数组有关系,比如借助数组对象实现最大值最小值
-
bind不调用函数,但是还想改变this指向,比如改变定时器内部的this指向
var btns = document.querySelectorAll('button'); for (var i = 0; i < btns.length; i++) { btns[i].onclick = function () { this.disabled = true; setTimeout(function () { this.disabled = false; }.bind(this), 2000)//bind写在定时器函数的外面,this指向btn这个对象 } }
高阶函数
是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出
function fn(a, b, callback) {
console.log(a + b);
callback && callback();
}
fn(1, 2, function() {
console.log('我是最后调用的');
});
8.闭包
一个作用域可以访问另外一个函数内部的局部变量,是延申了变量的作用范围
// 闭包(closure) 指有权访问另一个函数作用域中变量的函数
// 简单理解:一个作用域可以访问另外一个函数内部的局部变量
// 闭包:我们fun 这个函数作用域 访问了另外一个函数 fn 里面的局部变量num
/*function fn() {
var num = 5;
function fun() {
console.log(num);
}
fun()
}
fn()
*/
// 利用闭包,我们外面的作用域可以访问fn内部的局部变量
//就是延申了变量的作用范围
function fn() {
var num = 10;
// function fun() {
// console.log(num);
// };
// return fun;
return function () {
console.log(num);
}
}
var f = fn();
f();
9.递归
函数内部自己调用自己
/*
var num = 1;
function fn() {
console.log('打印6句话');
if (num == 6) {
return;//
}
num++;
fn();
}
fn();
*/
// 利用递归求1~n的阶乘
function fn(n) {
if (n == 1) {
return 1
}
return n * fn(n - 1)
}
console.log(fn(3));
</script>
利用递归遍历数据
// 输入id,就可以返回对应的数据对象
var data = [{
id: 1,
name: '家电',
goods: [{
id: 11,
gname: '冰箱',
goods: [{
id: 111,
gname: '海尔'
}, {
id: 112,
gname: '美的'
},]
}, {
id: 12,
gname: '洗衣机'
}]
}, {
id: 2,
name: '服饰'
}];
function select(json, id) {
var o = {};
json.forEach(function (value) {
if (value.id == id) {
o = value;
} else if (value.goods && value.goods.length > 0) {
o = select(value.goods, id)
}
})
return o;
}
console.log(select(data, 111));
10.拷贝
浅拷贝
浅拷贝对于更深层次对象级别只拷贝引用,所以改值对两个对象都有影响
var obj = {
id: 1,
name: 'andy',
msg: {
age: 17,
}
};
var o = {};
for (var i in obj) {
// k是属性名,obj[k]属性值
o[i] = obj[i];
}
//
o.msg.age = 12;
// 浅拷贝对于更深层次对象级别只拷贝引用,所以改值对两个对象都有影响
console.log(obj);
console.log(o);
------------------------------------------
ES6浅拷贝语法糖Object.assign()
Object.assign(o,obj);//把obj拷贝给o
console.log(o);
深拷贝
修改源对象更深层次对象不会影响拷贝的对象的值,互不影响
var obj = {
id: 1,
name: 'andy',
msg: {
age: 18
},
color: ['pink', 'red']
};
var o = {};
function deepCopy(newObj, oldObj) {
for (var i in oldObj) {
var item = oldObj[i];
if (item instanceof Array) {
newObj[i] = [];
deepCopy(newObj[i], item)
} else if (item instanceof Object) {
newObj[i] = {};
deepCopy(newObj[i], item)
} else {
newObj[i] = item;
}
}
}
deepCopy(o, obj);
console.log(o);
console.log(obj);
obj.msg.age = 1;
console.log(o);
11.正则表达式
正则在js中的创建使用
// 方法1.利用RegExp对象来创建正则表达式
var regexp = new RegExp(/123/);
console.log(typeof regexp);
console.log(regexp);
//2.利用字面量创建正则表达式
var rg = /123/;
// 3.test方法用来检测字符串是否符号正则表达式要求的规范
console.log(rg.test(123));//true
console.log(rg.test('abc'));//false
console.log(regexp.test(1234));//true
边界符的使用
//正则表达式里面不需要加引号 不管是数字还是字符型
// 边界符^ $
var rg = /abc/;//正则表达式里面不需要加引号 不管是数字还是字符型
// /abc/ 只要包含有abc这个字符串返回的都是true
console.log(rg.test('abc'));
console.log(rg.test('abcd'));
console.log(rg.test('aabcd'));
console.log('--------------');
var reg = /^abc/; //必须以abc开头
console.log(reg.test('abc'));
console.log(reg.test('abcd'));
console.log(reg.test('aabcd'));//false
console.log('--------------');
var reg = /abc$/; //必须以abc结尾
console.log(reg.test('abc'));
console.log(reg.test('abcd'));//false
console.log(reg.test('dabc'));
console.log('--------------');
var reg = /^abc$/; //精确匹配,要求必须是abc 字符串才符合规范
console.log(reg.test('abc'));
console.log(reg.test('abcd'));//false
console.log(reg.test('aabcd'));//false
console.log(reg.test('abcabc'));//false
字符类
// 字符类: [] 表示有一系列字符可供选择,只要1匹配其中一个就可以了
// var rg=/abc/; 只要包含abc就可以
// 字符类: [] 表示有一系列字符可供选择,只要1匹配其中一个就可以了
var rg = /[abc]/; //只要包含有a 或者包含有b 或者包含有C 都返回为true
console.log(rg.test('andy'));
console.log(rg.test('baby'));
console.log(rg.test('color'));
console.log(rg.test('red'));//false
console.log('------------------');
var rg1 = /^[abc]/; //只要其中任何一个开头都可以
console.log(rg1.test('aa'));
console.log(rg1.test('a'));
console.log(rg1.test('b'));
console.log(rg1.test('c'));
console.log(rg1.test('dabc'));//false
console.log('------------------');
var rg1 = /^[abc]$/; //3选1 只有是a 或者是b 或者是c 这3个字母才返回true
console.log(rg1.test('aa'));//false
console.log(rg1.test('a'));
console.log(rg1.test('b'));
console.log(rg1.test('c'));
console.log(rg1.test('abc'));//false
console.log('------------------');
var rg1 = /^[a-z]$/; //26个英文字母任何一个字母返回的都是true -表示a到z的范围
console.log(rg1.test('g'));
console.log(rg1.test('A'));//false
console.log(rg1.test('z'));
console.log(rg1.test(1));//false
console.log('------------------');
// 字符组合
var rg1 = /^[a-zA-Z0-9_-]$/; //26个英文字母(大小写)任何一个字母返回的都是true -表示范围
console.log(rg1.test('a'));
console.log(rg1.test('B'));
console.log(rg1.test('8'));
console.log(rg1.test('_'));
console.log(rg1.test('-'));
console.log(rg1.test('!'));//false
console.log('------------------');
// 如果中括号里面有^ 表示取反的意思 千万和我们边界符^ 别混淆
var rg1 = /^[^a-zA-Z0-9_-]$/; //26个英文字母(大小写)任何一个字母返回的都是true -表示范围
console.log(rg1.test('a'));
console.log(rg1.test('B'));
console.log(rg1.test('8'));
console.log(rg1.test('_'));
console.log(rg1.test('-'));
console.log(rg1.test('!'));//true
量词
// 量词符: 用来设定某个模式出现的次数
// 简单理解: 就是让下面的a这个字符重复多少次
// var reg = /^a$/;
// * 相当于 >= 0 可以出现0次或者很多次
var reg = /^a*$/;
console.log(reg.test(''));
console.log(reg.test('a'));
console.log(reg.test('aaa'));
// + 相当于 >= 1 可以出现1次或者很多次
// var reg = /^a+$/;
// console.log(reg.test('')); // false
// console.log(reg.test('a')); // true
// console.log(reg.test('aaaa')); // true
// ? 相当于 1 || 0
// var reg = /^a?$/;
// console.log(reg.test('')); // true
// console.log(reg.test('a')); // true
// console.log(reg.test('aaaa')); // false
// {3 } 就是重复3次
// var reg = /^a{3}$/;
// console.log(reg.test('')); // false
// console.log(reg.test('a')); // false
// console.log(reg.test('aaaa')); // false
// console.log(reg.test('aaa')); // true
// {3, } 大于等于3
var reg = /^a{3,}$/;
console.log(reg.test('')); // false
console.log(reg.test('a')); // false
console.log(reg.test('aaaa')); // true
console.log(reg.test('aaa')); // true
// {3,16} 大于等于3 并且 小于等于16
var reg = /^a{3,6}$/;
console.log(reg.test('')); // false
console.log(reg.test('a')); // false
console.log(reg.test('aaaa')); // true
console.log(reg.test('aaa')); // true
console.log(reg.test('aaaaaaa')); // false
</script>
括号
// 中括号 字符集合 匹配方括号中的任意字符
var reg = /^[abc]$/;
// a 也可以 b也可以 c 可以 a||b||c
// 大括号 量词符 里面表示重复次数
var reg=/^abc{3}$/; //它只是让c重复3次 abccc
console.log(reg.test('abc'));
console.log(reg.test('abcabcabc'));
console.log(reg.test('abaccc'));
console.log(reg.test('abccc'));//true
// 小括号 表示优先级
var reg=/^(abc){3}$/; //它只是让abc重复3次 abcabcabc
console.log(reg.test('abc'));
console.log(reg.test('abcabcabc'));//true
console.log(reg.test('abaccc'));
console.log(reg.test('abccc'));
替换
// 替换 replace
// var str = 'andy和red';
// // var str1=str.replace('andy','baby');
// var str1=str.replace(/andy/,'baby');
// console.log(str1);
var text=document.querySelector('textarea');
var btn=document.querySelector('button');
var div=document.querySelector('div');
btn.onclick=function(){
// g:全局匹配 i:忽略大小写 gi:全局匹配+忽略大小写
div.innerHTML=text.value.replace(/激情|gay/g,'**');
}
12.阮一峰ES6
12.let和const关键字
let关键字声明变量
-
let声明的变量只在所处于的块级作用域有效
-
块级作用域: 全局,函数
if(true){ let a=10 } console.log(a);// a is not defined
-
不存在变量提升
console.log(a); let a = 100;
-
存在暂时性死区
var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError let tmp; }
let经典面试题
var arr = [];
for (var i = 0; i < 2; i++) {
arr[i] = function () {
// 函数内部没有定义i的代码,所以会按原型链往上查找
console.log(i);
}
}
arr[0]();//2
arr[1]();//2
// 因为i是全局变量,函数调用的时候for早就执行完了
var arr1 = [];
//let有块级作用域
for (let i = 0; i < 2; i++) {
arr1[i] = function () {
console.log(i);
}
}
arr1[0]();//0
arr1[1]();//1
const声明常量⭐️
-
const声明的常量只在所处于的块级作用域有效
-
使用const关键字声明的常量必须赋初始值
-
常量赋值后不能更改两种情况
// 常量赋值后,值不能修改 // const a = 3; // a = 4; // 但是复杂数据类型可以这样 const arr = [1, 2]; arr[0] = '上'; arr[1] = '下'; console.log(arr);//['上','下'] arr = ['a', 'n']//报错,不能这样改值,这样更改了内存地址
-
var let const 函数级作用域 块级作用域 块级作用域 变量提升 不存在变量提升 不存在变量提升 值可更改 值可更改 值不可更改
作用域
<button>1</button>
<button>2</button>
<button>3</button>
<script>
var btns = document.querySelectorAll('button');
// for (var i = 0; i < btns.length; i++) {
// btns[i].addEventListener('click', function () {
// console.log(i);//3
// })
// }
// 解决方法1
// for (let i = 0; i < btns.length; i++) {
// btns[i].addEventListener('click', function () {
// console.log(i);//3
// })
// }
// 解决方法2
for (let i = 0; i < btns.length; i++) {
(function (i) {
btns[i].addEventListener('click', function () {
console.log(i);
})
})(i)
}
</script>
对象字面量增强写法
<script>
// 属性的增强写法
const name = 'why';
const age = 16;
const height = 188;
/*Es5写法
const obj = {
name: name,
age: age,
height: height
}
*/
const obj = {
name,
age,
height
}
console.log(obj);
// 函数方法的简写
//Es5的写法
let obj1 = {
test: function () {
console.log(777);
},
test() {
console.log('我是简写');
}
}
</script>
13.解构赋值
从数组和对象中提取值,对变量进行赋值,这被称为解构,j建议直接看文档
数组解构
let ary = [1, 2, 3];
// 多出来的解构失败,显示undefined
let [a, b, c, d] = ary;
console.log(a);
console.log(b);
console.log(c);
console.log(d);//undefined
对象解构
使用变量的名字匹配对象的属性,匹配成功将对象属性的值赋值给变量
-
正常情况下,对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
let { bar, foo } = { foo: 'c', bar: 'a' } console.log(bar);//a console.log(foo);//c
//对象的属性没有次序,变量必须与属性同名,才能取到正确的值。 let { bar, foo } = { foo: 'c', bar: 'a' } console.log(bar);//a console.log(foo);//c let { baz } = { hd: 'aaa', gr: 'bbb' }; console.log(baz);//undefineds
-
如果变量与属性名不一样,还想要匹配成功则需要设置别名,利用别名解构
let { n: bm } = { a: 'c', g: 'k', n: 5 };
console.log(bm);//5
14.箭头函数
箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法
-
语法表达
const fn = () => { console.log(123); } fn();//123
-
// 如果函数体只有一句代码,且代码的执行结果就是返回值,可以省略大括号
const sum = (n1, n2) => n1 + n2;
var result = sum(3, 5);
console.log(result);//8
-
如果形参只有一个,可以省略小括号
const single = v => { alert(v); } single(20)
// 箭头函数不绑定this 箭头函数没有自己的this关键字 如果在箭头函数中使用this关键字将指向箭头函数定义位置中的this
// 局部作用域(函数作用域)
function fn() { console.log(this); return () => { console.log(this) } } const obj = { name: 'zhangsan' }; const resFn = fn.call(obj); resFn();
-
对象是不能产生作用域的
var age = 100; var obj = { age: 20, say: () => { console.log(this.age);//100 }, s: function () { console.log(this.age);//20 } } // 对象是不能产生作用域的 obj.say(); obj.s()
15.剩余参数
剩余参数是将剩余的元素放在一个数组中
// 剩余参数是将剩余的元素放在一个数组中
const sum = (...args) => {
var total = 0;
args.forEach(item => {
total += item;
})
return total;
}
console.log(sum(12, 34));
// 剩余参数+数组解构
let ary1 = ['张三', '李四', '王五'];
let [s1, ...s2] = ary1;//s2变成了一个数组
console.log(s1)
console.log(s2)
16.扩展运算符
扩展运算符可以将数组或者对象转为用逗号分隔的参数序列
// 扩展运算符可以将数组或者对象转为用逗号分隔的参数序列
let arr = ['a', 'b', 'c'];
// 这里没逗号是因为被当成了log方法的分隔符
console.log(...arr);//1 2 3
// 扩展运算符应用于数组合并
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let arr3 = [...arr1, ...arr2];
console.log(arr3);
//方法2
arr3.push(...arr1);
console.log(arr3);
利用扩展运算符将伪数组转换为真正的数组
var oDivs = document.getElementsByTagName('div');
console.log(oDivs);//实际上就是伪数组
var ary = [...oDivs];//数组
// 变成数组后就可以运用数组方法了
ary.push('a');
console.log(ary);
17.Array.form
1.将伪数组或可遍历对象转换为真正的数组
2.第2个参数为回调函数,
var arrayLike = {
'0': 1,
'1': 2,
'2': 3,
length: '3'
}
console.log(arrayLike);
// var newArr = Array.from(arrayLike);
//console.log(newArr);//[1,2,3];
// 第2个参数为回调函数
var newArr = Array.from(arrayLike, item => item * 2);
console.log(newArr);//[2,4,6]
18.模板字符串
// es6新增的创建字符串的方式,使用反引号定义
// let name=`这是一个模板字符串`;
// let a=`张飞`;
// console.log(`我的兄弟是${a}`);
// console.log(name);
// let result={
// name:'张三',
// age:20
// };
// let html=`
// <div>
// <span>${result.name}</span>
// <span>${result.age}</span>
// </div>
// `;
// console.log(html);
const fn = function () {
return '关羽';
}
let b = `你是${fn()}`;
console.log(b);
console.log(`付电费,
放到`);
19.Set,Map方法⭐️
类似于数组,但成员的值都是唯一的,没有重复的值
// es6提供了新的数据结构Set,它类似于数组,但是成员的值都是唯一的,没有重复的值
// Set本身是一个构造函数,用来生成Set数据结构
// const s1 = new Set();
// // size 表示此数据结构中包含多少值
// console.log(s1.size)
// // Set函数可以接收一个数组作为参数,用来初始化
// const s2 = new Set(["a", "b"]);
// console.log(s2.size)
// // 可以做到数组去重
// const s3 = new Set(["a", "a", "b", "b"]);
// console.log(s3.size);//2 具有去重功能
// console.log(s3)
// const ary = [...s3];
// console.log(ary)
const s4 = new Set();
// 向set结构中添加值 使用add方法 返回结构本身
s4.add('a').add('b');
console.log(s4.size);//2
// 从set结构中删除值 用到的方法是delete 返回布尔值
const r1 = s4.delete('c');
console.log(s4.size)
console.log(r1);
// 判断某一个值是否是set数据结构中的成员 使用has 返回布尔值
const r2 = s4.has('d');
console.log(r2)
// // 清空set数据结构中的值 使用clear方法
// s4.clear();
// console.log(s4.size);
// 遍历set数据结构 从中取值
const s5 = new Set(['a', 'b', 'c']);
s5.forEach(value => {
console.log(value)
})
20.Es6模块化
1.想要在nodejs中体验es6模块化
在package.json里面加入“type":‘module’
{
"type": "module",
"name": "code",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"then-fs": "^2.0.0"
}
}
2.默认导入和导出
默认导出
let n1 = 10
let n2 = 20
function show() {}
export default {
n1,
show
}
默认导入不要加{}
import m1 from './01.默认导出.js'
console.log(m1)
每个模块中,只允许使用唯一的一次export default
3.按需导入和导出
按需导出
export let s1 = 'aaa'
export let s2 = 'ccc'
export function say() {}
按需导入要加{}
取别名,这里给s2取了别名
import { s1, s2 as str2, say } from './03.按需导出.js'
console.log(s1)
console.log(str2)
console.log(say)
4.默认与按需导入导出写一块
export let s1 = 'aaa'
export let s2 = 'ccc'
export function say() {}
export default {
a: 20
}
导入
import info, { s1, s2 as str2, say } from './03.按需导出.js'
console.log(s1)
console.log(str2)
console.log(say)
console.log(info)
运行结果
aaa
ccc
[Function: say]
{ a: 20 }
5.直接运行模块中的代码
导出
for (let i = 0; i < 3; i++) {
console.log(i)
}
导入
import './05.直接运行模块中的代码.js'
运行结果
0
1
2
21.Promise
- 基本语法
const p = new Promise(function (resolve, reject) {
let date = '你是奔达嘛';
// resolve(date);
reject(date);//对应第then的第2个状态
}).then(function (value) {
console.log(value);
}, function (reason) {
console.error(reason);
})
-
catch
const p = new Promise((resolve, reject) => { setTimeout(() => { //设置 p 对象的状态为失败, 并设置失败的值 reject("出错啦!"); }, 1000) }); // p.then(function(value){}, function(reason){ // console.error(reason); // }); p.catch(function (reason) { console.warn(reason); });
-
读取文件
// 1.引入fs模块 const fs = require('fs') // 2.调用方法读取文件 //3. 使用 Promise 封装 const p = new Promise(function (resolve, reject) { fs.readFile('./resources/为学.md', (err, data) => { if (err) reject(err); resolve(data) }); }).then(value => { return new Promise(function (resolve, reject) { fs.readFile('./resources/插秧诗.md', (err, data) => { if (err) reject(err); resolve([value, data]) }); }) }).then(value => { return new Promise(function (resolve, reject) { fs.readFile('./resources/观书有感.md', (err, data) => { if (err) { reject(err) } else { value.push(data); resolve(value) } }) }) }).then(value => { console.log(value.toString()); }) // p.then(function (value) { // console.log(value.toString()); // }, function (item) { // console.log('读取失败'); // })
promise.all
Promise.all([
// new Promise((resolve, reject) => {
// $.ajax({
// url: 'url1',
// success: function (data) {
// resolve(data)
// }
// })
// }),
// new Promise((resolve, reject) => {
// $.ajax({
// url: 'url2',
// success: function (data) {
// resolve(data)
// }
// })
// })
new Promise((resolve, reject) => {
setTimeout(() => {
resolve({name: 'why', age: 18})
}, 2000)
}),
new Promise((resolve, reject) => {
setTimeout(() => {
resolve({name: 'kobe', age: 19})
}, 1000)
})
]).then(results => {
console.log(results);
22.async和await
async
// 只要返回的结果表示promise对象,返回的结果就是成功的Promise对象
async function fn() {
// async函数的返回值是 Promise 对象
// return '绝世武神'
//return; //undefined
//返回的结果是一个失败的promise
//throw new Error('出错啦!')
//返回的结果是一个Promise对象
return new Promise((resolve, reject) => {
// resolve('成功的数据')对应then的第1个参数
reject('失败的数据');//对应then的第2个参数
})
}
const hs = fn();
console.log(hs);
hs.then(success => {
console.log(success);
}, error => {
console.log(error);
})
await
const p = new Promise(function (resolve, reject) {
//resolve('成功的值');
reject('失败的值')
})
// await要放在async函数中
/* async function main() {
// await返回的结果就是promise对象成功的那个值
let result = await p;
console.log(result);
}*/
/*任何一个await语句后面的 Promise 对象变为reject状态,
那么整个async函数都会中断执行。
我们希望即使前一个异步操作失败,也不要中断后面的异步操作。
这时可以将第一个await放在try...catch结构里面,
这样不管这个异步操作是否成功,第二个await都会执行。*/
async function main() {
try {
let result = await p;
console.log(result);
} catch (e) {
console.log(e);//失败的值
}
}
main()
在async方法中,第一个await之前的代码会同步执行,await之后的代码会异步执行
const fs = require('fs');
function readWx() {
return new Promise(function (resolve, reject) {
fs.readFile('./resources/为学.md', (err, data) => {
if (err) reject(err);
resolve(data)
});
})
};
function readCys() {
return new Promise(function (resolve, reject) {
fs.readFile('./resources/插秧诗.md', (err, data) => {
if (err) reject(err);
resolve(data)
});
})
};
function readGsyg() {
return new Promise(function (resolve, reject) {
fs.readFile('./resources/观书有感.md', (err, data) => {
if (err) reject(err);
resolve(data)
});
})
}
console.log('A');
async function main() {
console.log('B');
let Wx = await readWx();
let Cys = await readCys();
let Gsyg = await readGsyg();
console.log(Wx.toString());
console.log(Cys.toString());
console.log(Gsyg.toString());
console.log('C');
}
main();
console.log('D');
// 在async方法中,第一个await之前的代码会同步执行,await之后的代码会异步执行
//ABD....C