一、let 和 const
1-1 let和const
-
let和const是什么
声明变量或声明常量
var声明变量
let代替var,声明变量
const声明常量constant -
let和const的用法
和var一样 -
什么是变量,什么是常量 var、let声明的就是变量,变量一旦初始化之后,还可以重新赋值
const声明的就是常量,常量一旦初始化,就不能重新赋值了,否则就会报错
1-2 const
-
为什么需要const?
就是为了那些一旦初始化就不希望重新赋值的情况设计的 -
const的注意事项
2.1 使用const声明变量,一旦声明,就必须立即初始化,不能留到以后赋值
2.2 const声明的常量,允许在不重新赋值的情况下修改它的值
const person = {username:"Alex"};
person.username = "ZhangSan";
console.log(person);
- 什么时候用const,什么时候用let
当你不知道使用const还是let的时候,建议使用const,在之后的某一天如果想要修改的时候,他会报错,这样之后也好修改。
1-3 let、const与var的区别
- 重复声明
已经存在的变量或常量,又声明了一遍
var允许重复声明,let、const不允许 - 变量提升
var会提升变量的声明到当前作用域的顶部
相当于
var a;
console.log(a);
a = 1;
console.log(a);
let、const不存在变量提升
养成良好的编程习惯,对于所有的变量或常量,做到先声明,后使用。
- 暂时性死区
只要作用域内存在let、const,它们所声明的变量或常量就自动"绑定"这个区域,不再受到外部作用域的影响
//let、const存在暂时性死区
let a = 2;
let b = 1;
function func() {
console.log(a);
let a = 1;
}
func()
- window对象的属性和方法
全局作用域中,var声明的变量,通过function声明的函数,会自动变成window对象的属性或方法
let、const不会
1-4 块级作用域
- 什么是块级作用域
var没有块级作用域,let/const有块级作用域 - 作用域链
作用域链:内层作用域->外层作用域->...->全局作用域
3. 有哪些块级作用域
{}
for(){}
while(){}
do{}while()
if(){}
switch(){}
1-5 let和const的应用
二、模板字符串
2-1 模板字符串
- 认识模板字符串
const username2 = `alex`;
console.log(username1,username2,username1===username2)
- 模板字符串与一般字符串的区别
const person = {
username:'Alex',
age:18,
sex:'male'
};
const info =
'我的名字是:'+
person.username +
',今年:' +
person.age +
'岁了';
console.log(info)
const info = `我的名字是:${person.username},
性别:${person.sex},
今年${person.age}岁了`
console.log(info);
//和其他东西一起使用的时候,使用模板字符串,方便注入
//其他情况下使用模板字符串或一般字符串都行
2-2 模板字符串的注意事项
- 输出多行字符串
一般字符串
const info = `第1行\n第2行`
console.log(info);
//模板字符串
const info = `第1行\n第2行`
const info = `第1行
第2行`
console.log(info);
//模板字符串中,所有的空格、换行或缩进都会被保留在输出之中
- 输出`和\等特殊字符
const info = `\``;
console.log(info);
- 模板字符串的注入
${}
const username = 'alex';
const person = {age:18,sex:'male'};
const getSex = function(sex){
return sex === 'male'?'男':'女';
};
const info =`${username},${person.age},${getSex(person.sex)}`;
console.log(info);
只要最终可以得出一个值的就可以通过${}注入到模板字符串中
2-3 模板字符串的应用
三、箭头函数
3-1 箭头函数
- 认识箭头函数
const add = (x,y)=>{
return x + y;
};
console.log(add(1,1))
-
箭头函数的结构
const/let 函数名 = 参数 => 函数体 -
如何将一般函数改写成箭头函数
// 声明形式
function add(){}
// 声明形式->函数表达式形式
const add = function () {};
// 函数表达式形式->箭头函数
const add = () => {};
3-2 箭头函数的注意事项
- 单个参数
const add = (x) => {
return x + 1
};
//单个参数可以省略圆括号
const add = x => {
return x + 1;
}
console.log(add(1));
//无参数或多个参数不能省略圆括号
const add = () => {
return 1 + 1;
};
const add = (x,y) => {
return x + y;
};
console.log(add(1,1));
- 单行函数体
// 单行函数体可以同时省略{}和return
const add = (x,y) => {
return x + y;
};
const add = (x,y) => x + y
console.log(add(1,1));
// 多行函数体不能再化简了
const add = (x,y) => {
const sum = x + y
return sum;
};
- 单行对象
const add = (x,y) => {
return {
value: x + y
}
}
const add = (x,y) => ({
value: x + y;
return undefind;
})
// 如果箭头函数返回单行对象,可以在{}外面加上(),让浏览器不在认为那是函数体的花括号
const add = (x,y) => [x,y];
console.log(add(1,1))
3-3 this指向1
- 全局作用域中的this指向
console.log(this) //window
- 一般函数(非箭头函数)中的this指向
//'use strict'
function add(){
console.log(this);
}
// 严格模式就指向undefined
add() //undefined -> window(非严格模式下)
// window.add();
const calc = {
add:add
};
// calc.add(); // calc
const adder = calc.add;
adder(); // undefined -> window(非严格模式下)
document.onclick = function() {
console.log(this);
};
function Person(username) {
this.username = username;
console.log(this);
}
const p = new Person('Alex'); //构造函数指向的是他的实例对象
//只有在函数调用的时候this指向才确定,不调用的时候,不知道指向谁
//this指向和函数在哪儿调用没关系,只和谁在调用有关
3-4 this指向2
- 箭头函数中的this指向
箭头函数没有自己的this
const calc = {
add:() => {
console.log(this)
}
};
calc.add();//window
3-5 不适用箭头函数的场景
- 作为构造函数
箭头函数没有this
const Person = () => {};
new Person();
-
需要this指向调用对象的时候
-
需要使用arguments的时候
箭头函数中没有arguments
3-6 箭头函数的应用
<button id="btn">开始</button>
<span id="result">0</span>
<script>
const btn = document.getElementById('btn');
const result = document.getElementById('result');
const timer = {
time:0,
strat:function(){
console.log(this);
// const th
btn.addEventListener('click',() => {
setInterval(()=>{
this.time++;
result.innerHTML = this.time;
console.log(this);
},1000)
},false)
}
}
timer.strat();
</script>
数组的解构赋值
4-1 数组的解构赋值
- 认识解构赋值
const arr = [1,2,3];
const a = arr[0]
const a = arr[0]
- 什么是解构赋值
解构某一数据的结构,将我们想要的东西提取出来,赋值给变量或常量。
4-2 数组解构赋值的原理
- 模式(结构)匹配
[] = [1,2,3]; - 索引值相同的完成赋值
[a,b,c] = [1,2,3];
console.log(a,b,c);
const = [1,[2,4,5],3]
const [a,[,,b],c] = [1,[2,4,5],3];
console.log(a,b,c);
4-3 数组解构赋值的默认值
- 默认值得基本用法
// const [a,[,,b],c] = [1,[2,4,5],3];
// console.log(a,b,c);
// const [a,b] = []
const [a,b] = [undefined,undefined];
console.log(a,b);
- 默认值的生效条件
只有当一个数组成员严格等于(===)undefined时,对应的默认值才会生效。
3.默认值表达式
如果默认值是表达式,默认值表达式是惰性求值的
const func = () => {
console.log('我被执行了');
return 2;
};
const [x=func()] = [1]
console.log(x);
4-4 数组解构赋值的应用
- 常见的类数组的解构赋值
function func() {
console.log(arguments);
}
func();
func(1,2)
- 函数参数的解构赋值
const array = [1,1];
// const add = arr => arr[0] + arr[1];
const add = ([x,y]) => x + y
// console.log(add(array));
console.log(add([]));
- 交换变量的值
let x = 1;
let y = 2;
// let tmp = x;
// x = y;
// y = tmp;
// console.log(x,y);
[x,y] = [y,x];
console.log(x,y);
五、对象的解构赋值
5-1 对象的解构赋值
- 模式(结构)匹配
{} = {} - 属性名相同的完成赋值
// 属性名相同赋值
// const {age,username} = {username:'Alex',age:18}
// const {'age':age,'username':username} = {username:'Alex',age:18}
// console.log(age,username);
//取别名
const {age:age,username:uname} = {
username:'Alex',age:18}
console.log(age,uname);
5-2 对象解构赋值的注意事项
- 默认值的生效条件
对象的属性值严格等于undefined时,对应的默认值才会生效
//对象渲染的注意事项
//属性名添加默认值时,注意是写等号
const {username = 'Zhangsan',age = 0} = {username:'alex'}
console.log(username,age);
-
默认值表达式
如果默认值是表达式,,默认值表达式是惰性求值的 -
将一个已经声明的变量用于解构赋值
// let x = 2;
// ({x} = {x: 1})
// console.log(x);
// [x] = [1];
// console.log(x);
- 可以取到继承的属性
const {toString} = {}
console.log(toString);
//对象toString继承自Object的,在Object的prototype上
5-3 对象解构赋值的应用
- 函数参数的解构赋值
const logPersonInfo = ({age,username}) => console.log(username,age);
logPersonInfo({username:'alex',age:18});
- 复杂的嵌套
const obj = {
x:1,
y:[2,3,4],
z:{
a:5,
b:6
}
};
// const {x,y,z} = obj;
// console.log(x,y,z);
const {
y,
y:[,yy]
} = obj
console.log(yy,y);
5-4 其他数据类型的解构赋值
- 字符串的解构赋值
2.数值和布尔值的解构赋值
等号右边的值转为对象
3.undefined 和null的解构赋值
由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错
六、对象字面量的增强
6-1 方括号语法
- 方括号语法的用法
const prop = 'age';
const person = {};
// person.prop = 18;
person[prop] = 18;
const person = {
[prop]:18
}
console.log(person);
2.方括号中可以放什么
// ${}
// [值或通过计算可以得到值的(表达式)]
const prop = 'age';
const func = () => 'age';
const person = {
// [prop]:18
// ['sex']:'male'
// [func()]:18
}
console.log(person)
3.方括号语法和点语法的区别
点语法是方括号语法的特殊形式
const person ={};
// person.age 等价于person['age']
// 属性名由数字、字母、下划线以及$构成,并且数字还不能打头的时候可以使用点语法
// age18_$ √
// 18age x
// 合法标识符可以用来作为变量或常量名
// 当你的属性或方法名是合法标识符时,可以使用点语法,其他情况下请使用方括号语法
6-2 属性和方法的简洁表示法
//1. 对象字面量是什么
//实例化构造函数生成对象
const person = new Object();
person.age = 18;
person.speak = function () {};
// 对象字面量
// const person = {
age:18,
speak:function () {}
};
//2.属性的简洁表示法
//键名和变量或常量名一样的时候,可以只写一个
const age = 18
const person = {
age
}
console.log(person);
// 3.方法的剪辑表示法
const person = {
speack () {}
}
console.log(person)
七 函数参数的默认值
7-1 函数参数的默认值
// 1.认识函数参数的默认值
// 调用函数的时候传参了,就用传递的参数:如果没传参,就用默认值
//multiply(2,1);
//multiply(2);
// 2.函数参数默认值的基本用法
//(过去方法)
const multiply = (x,y) => {
if(typeof y==='undefined') {
y = 1;
}
return x * y
}
//(现在方法)
//const multiply = (x,y=1) => x*y;
console.log(multiply(2))
7-2 函数参数默认值的注意事项
// 1.默认值的生效条件
// 不传参数,或者明确的传递 undefined作为参数,只有这两种情况下,默认值才会生效
const multiply = (x,y = 1) => x * y;
console.log(multiply(2,0));
console.log(multiply(2,null));
console.log(multiply(2,undefined));
console.log(multiply(2));
// 2.默认值表达式
// 如果默认值是表达式,默认值表达式惰性求值的
// 3.设置默认值的小技巧
// 函数参数的默认值,最好从参数列表的右边开始设置
// console.log(multiply(undefined,2));
7-3 函数参数默认值的应用
// 1.接受很多参数的时候
const logUser = (username = 'ZhangSan',age = 0,sex = 'male')=>console.log(username,age,sex);
logUser('Alex',18,'male');
logUser();
// 2. 接受一个对象作为参数
//const logUser = options=>console.log(options.username,options.age,sex);
const logUser = ({username = 'ZhangSan',age = 0,sex = 'male'} = {}) => console.log(options.username,options.age,options.sex)
// logUser({
// username:'alex',
// age:18,
// sex:'male'
// });
logUser({username:'alex'});
logUser({});
logUser();
八 剩余参数
8-1 剩余参数
// 1.认识剩余参数
const add = (x,y,z,...args) => {};
// 2. 剩余参数的本质
const add = (x,y,...args) => {
console.log(x,y,args);
};
add(1,2,3);
//剩余参数永远是是个数组,即使没有值,也是空数组
8-2 剩余参数的注意事项
// 1. 箭头函数的剩余参数
// 箭头函数的参数部分即使只有一个剩余参数,也不能省略括号
// const add = (...args) => {};
// 2. 使用剩余参数替代 arguments获取实际参数
// const add = function () {
// console.log(arguments);
//}
const add = () => {
console.log(arguments);
}
add(1,2);
//3. 剩余参数的位置
//剩余参数只能是最后一个参数,之后不能再有其他参数,否则会报错
const add = (x,...args,y) => {
console.log(args);
}
8-3 剩余参数
// 1. 完成add函数
const add = (...args) => {
let sum = 0;
for(let i = 0;i < args.length:i++) {
sum += args[i];
}
return sum
}
console.log(add(1,2,3));
// 2.与解构赋值结合使用
// 剩余参数不一定非要作为函数参数使用
// const [num,...args] = [1,2,3,4];
// 必须是最后一个
// const [...args,num] = [1,2,3,4];
console.log(numm,args);
//const func = ([num,...args]) => {};
//func([1,2,3]);
const {x,y,...z} = {a:3,x:1,y:2,b:4};
console.log(x,y,z)
九 数组的展开运算符
9-1 数组的展开运算符
// 1.认识展开运算符
// [3,1,2]
// Math.min
console.log(Math.min([3,1,2]));
// 2. 数组展开运算符的基本用法
// console.log(Math.min(...[3,1,2]))
//相当于
console.log(Math.min(...[3,1,2]));
9-2 区别剩余参数和展开运算符
// 1.根本区别
//展开运算符
// [3,1,2] -> 3,1,2
//剩余参数
//3,1,2 -> [3,1,2]
// 2.区别剩余参数和展开运算符
// 展开运算符
const add = (...args) => {
console.log(...args)
};
add(1,2,3)
[...[1,2,3],4];
// [1,2,3] -> 1,2,3
9-3 数组展开运算符的应用
//1. 复制数组;
const a = [1,2];
//const b = a;
//a[0] = 3;
//console.log(b);
const c = [...a];
//const c = [1,2];
a[0] = 3;
console.log(a);
console.log(c);
// 2.合并数组
const a = [1,2];
const b = [3];
const c = [4,5];
console.log([...a,...b,...c]);
// 3.字符串转为数组
// 字符串可以按照数组的形式展开
// console.log(...'alex');
// 4. 常见的类数组转化为数组
// arguments
function func() {
console.log([...arguments]);
}
func(1,2);
//NodeList
// console.log(document.querySelectorAll('p'));
// console.log([...document.querySelectorAll('p')].push)
十 对象的展开运算符
10-1 对象的展开运算符
// 1. 展开对象
// 对象不能直接展开,必须在{}中展开
const apple = {
color:'红色',
shape:'球形',
taste:'甜'
}
//对象的展开:把属性罗列出来,用逗号分隔,放到一个{}中,构成新对象
console.log({...apple}) === apple;
// 2. 合并对象
const apple = {
color:'红色',
shape:'球形',
taste:'甜'
};
//console.log({...pen});
//console.log({...apple,...pen});
//新对象拥有全部属性,相同属性,后者覆盖前者
//console.log({...pen,...apple});
//相当于
//console.log({
// use:'写字',
// color:'红色',
// shape:'球形',
// taste:'甜'
});
10-2 对象展开运算符的注意事项
// 1. 空对象的展开
// 如果展开一个空对象,则没有任何效果
// console.log({...{}});
// console.log(...{},a:1);
//2. 非对象的展开
//如果展开的不是对象,则会自动将其转为对象,再将其属性罗列出来
// console.log({...1});
// console.og(new Object(1));
// console.log({...undefined});
// console.log({...null});
// console.log({...true});
// 如果展开运算符后面是字符串,它会自动转成一个类似数组的对象,因此返回的不是空对象
// console.log({...'alex'});
// console.log([...'alex']);
// console.log(...'alex');
console.log({...[1,2,3]});
// 3.对象中对象属性的展开
// 不会展开对象中的对象属性
const apple = {
feature:{
taste:'甜'
}
};
const pen = {
feature:{
color:'黑色',
shape:'圆柱形'
},
use:'写字'
}
//console.log({...apple});
console.log({...apple,...pen});
//相当于
console.log({
feature:{
taste:'甜'
}
//下面的feature覆盖了上面的feature
feature:{
color:'黑色',
shape:'圆柱形'
},
use:'写字'
})
10-3 对象展开运算符的应用
// 1. 复制对象
// const a = {x:1 , y:2};
// cosnt b = a;
// const c = {...a};
// console.log(c,c===a);
//2. 用户参数和默认参数
//add(1,2,3);
const logUser = userParam => {
const deaultParam = {
username:'ZhangSan',
age:0,
sex:'male'
};
//const param = {...defaultParam,...userParam};
// console.log(param.username);
const {username,age,sex} = {...
defaultParam,...userParam};
console.log(username,age,sex);
}
十一 Set
11-1 Set是什么
// 1.什么是Set
// 集合
[1,2];
// 数组是一系列有序的数据集合
//Set 是一系列无序、没有重复值的数据集合
//2.理解Set
console.log(1,2,1);
console.log(new Array(1,2,1));
cosnt s = new Set();
s.add(1);
s.add(2);
//Set中不能有重复的成员
s.add(1);
console.log(s);
//Set没有下标去标示每一个值,所有Set是无序的,也不能像数组那样通过下标去访问Set的成员
11-2 Set实例的方法和属性
// 1. 方法
// add
const s = new Set();
s.add(1).add(2).add(2);
// console.log(s);
// has
console,log(s.has(1));
console.log(s.has(3));
//delete
S.delete(1);
//使用delete删除不存在的成员,什么都不会发生,也不会报错
// s.delete(3);
// console.log(S);
//clear
// s.clear
// console.log(s);
//forEach
console.log(s);
s.forEach(function(value,key,set) {
// Set中value = key
// console.log(value,key,set === s);
console.log(this);
},document);
//按照成员添加进集合的顺序遍历
//2.属性
//size
console.log(s.size);
11-3 Set构造函数的参数
// 1.数组
// const s = new Set([1,2,1]);
// console.log(s);
// // 2.字符串、arguments、NodeList、Set等
// console.log(new Set('hi'));
// function func() {
// console.log(new Set(arguments));
// }
// func(1,2,1);
// console.log(new Set(document.querySelectorAll('p')));
// const s = new Set([1,2,1]);
// console.log(new Set(s) === s);
// console.log(s);
11-4 Set构造函数的注意事项
//1.判断重复的方式
// const s = new Set([1,2,1]);
// const s = new Set([NaN,1,NaN])
// console.log(s);
// console.log(1 === 1);
// Set对于重复值的判断基本遵循严格相等(===)
// 但是对于NaN的判断与 === 不同,Set中NaN等于NaN
// const s = new Set();
// s.add({}).add({});
// console.log({}==={});
// console.log(s);
//2. 什么时候使用Set
// ① 数组或字符串去重时
// ② 不需要通过下标访问,只需要遍历时
// ③ 为了使用Set提供的方法和属性时(add delete clear has forEach sizs等)
11-5 Set的应用
// 1. 数组去重
// [1,2,1]
// const s = new Set([1,2,1]);
// console.log(s);
// // s.forEach
// console.log([...s]);
// 2.字符串去重
//'abbacbd'
// const s = new Set('abbacbd');
// console.log([...s].join(''));
// console.log([...new Set('abbacbd')].join(''));
//3. 存放 DOM 元素
// console.log(document.querySelectorAll('p'));
// const s = new Set(document.querySelectorAll('p'));
// s.forEach((value) => {
// console.log(value);
// value.style.color = 'red';
// value.style.backgroundColor = 'yellow';
// });
十二 Map
12-1 Map是什么
// 12 Map
// Map是什么
// 映射
// Map和对象都是键值对的集合
// 键 -> 值, key -> value
// const person= {
// name:'alex',
// age:18,
// }
// const m = new Map();
// m.set('name','alex');
// m.set('age',18);
// console.log(m);
//2. Map和对象的区别
// 对象一般用字符串当作键
// const obj = {
// name:'alex',
// true:'true',
// [{}]:'object'
// }
// console.log(obj);
// console.log({}.toString())
// 基本的数据类型:数字、字符串、布尔值、undefined、null
// 引用数据类型:对象([]、{}、函数、Set、Map等)
// 以上都可以作为Map的键
// const m = new Map();
// m.set('name','alex');
// m.set (true,'true');
// m.set({},'object');
// m.set(new Set([1,2]),'set');
// m.set(undefined,'undefined')
// console.log(m);
12-2 Map实例的方法和属性
// 1.方法
// set
// const m = new Map();
// //使用set添加的新成员,键如果已经存在,后添加的键值对覆盖已有的
// m.set('age',18).set(true,'true').set('age',20);
// console.log(m);
// Map有set和get方法可以添加和获取
// Set只有add可以添加不可以对单个键获取
// get
// console.log(m);
// console.log(m.get('age'));
// //get获取不存在的成员,返回undefined
// console.log(m.get('true'));
// // has
// console.log(m.has('age'));
// // delete
// m.delete('age');
// m.delete('name');
// // 使用delete删除不存在的成员,什么都不会发生,也不会报错
// console.log(m);
// clear
// m.clear();
// console.log(m);
// forEach
// m.forEach (function(value,key,map) {
// console.log(value,key,map === m);
// console.log(this);
// },document)
// // 2. 属性
// // size
// // 对象没有类似的属性
// console.log(m.size);
12-3 Map构造函数的参数
// 1. 数组
// console.log(new Map(['name','alex','age']));
// 只能传二维数组,而且必须体现出键和值
// console.log(new Map([
// ['name','alex'],
// ['age',18]
// ])
// );
// //2. Set、Map等
// // Set
// // Set中也必须体现出键和值
// const s = new Set([
// ['name','alex'],
// ['age',18]
// ])
// console.log(s);
// Map
// const m1 = new Map([
// ['name','alex'],
// ['age',18]
// ])
// console.log(m1);
// const m2 = new Map(m1);
// console.log(m2,m2 === m1);
12-4 Map的注意事项
// 1. 判断键名是否相同的方式
// 基本遵循严格相等(===)
// 例外就是NaN,Map中NaN也是等于NaN
// console.log(NaN === NaN);
// const m = new Map();
// m.set(NaN,1).set(NaN,2);
// console.log(m);
// // 2. 什么时候使用Map
// // 如果只是需要 key -> value 的结构,
//或者需要字符串以外的值做键,使用Map更合适
// // 只有模拟现实世界的实体时,才使用对象
// const person = {}
12-5 Map的应用
// Map的应用
// const [p1,p2,p3] = document.querySelectorAll('p');
// const m = new Map();
// m.set(p1,'red');
// m.set(p2,'green');
// m.set(p3,'blue');
// const m = new Map([
// [p1,{
// color:'red',
// backgroundColor:'yellow',
// fontSize:'40px'
// }],
// [p2,{
// color:'green',
// backgroundColor:'pink',
// fontSize:'40px'
// }],
// [p3,{
// color:'blue',
// backgroundColor:'orange',
// fontSize:'40px'
// }]
// ])
// m.forEach((propObj,elem) => {
// for(const p in propObj) {
// elem.style[p] = propObj[p];
// }
// })
// console.log(m);
//使用map方法
const m1 = new Map([
['color','red'],
['backgroundColor','yellow'],
['fontSize','40px']
])
const m2 = new Map([
['color','green'],
['backgroundColor','pink'],
['fontSize','40px']
])
const m3 = new Map([
['color','blue'],
['backgroundColor','orange'],
['fontSize','40px']
])
const m = new Map([
[p1,m1],
[p2,m2],
[p3,m3]
])
console.log(m);
m.forEach((map,elem) => {
map.forEach((propObj,prop) => {
elem.style[prop] = propObj
// elem.style.color = propObj
// console.log(prop,propObj);
})
})
十三 遍历
13-1 Iterator是什么
//1. Iterator的作用
// Iterator: 遍历器(迭代器)
// for()
// [1,2].forEach
// new Set().forEach
//Iterator 也是用来遍历的
//2.寻找 Iterator
// console.log(Iterator);
// console.log([1,2][Symbol.iterator]());
// //3.使用Iterator
// const it = [1,2][Symbol.iterator]();
// console.log(it.next()); //{value: 1, done: false}
// console.log(it.next()); //{value: 1, done: false}
// console.log(it.next()); //{value: undefined, done: true}
//it: 可遍历对象 (可迭代对象)
//Symbol.iterator:可遍历对象的生成方法
//4.什么是Iterator
//Symbol.iterator (可遍历对象的生成方法) -> it (可遍历对象) -> it.next() -> ...(直到done为true)
13-2 Iterator解惑
// 1.为什么需要Iterator遍历器
// 遍历数组:for循环和forEach方法
// 遍历对象:for in 循环
// Iterator遍历器是一个统一的遍历方式
// console.log([][Symbol.iterator]());
// console.log({}[Symbol.iterator]);
// 2. 如何更方便的使用Iterator
// Symbol.Iterator -> it -> next();
// 我们一般不会直接使用Iterator去遍历
13-3 for...of的用法1
// 1. 认识for...of
// const arr = [1,2,3];
// const it = arr[Symbol.iterator]();
// // console.log(it.next());
// // console.log(it.next());
// // console.log(it.next());
// // console.log(it.next());
// // let next = it.next();
// // console.log(next);
// // while(!next.done) {
// // console.log(next.value);
// // next = it.next();
// // }
// for(const item of arr) {
// console.log(item);
// }
//for...of循环只会遍历出那些done为false时,对应的value值
13-3 for...of的用法2
//2.与break、continue一起使用
// const arr = [1,2,3];
// for(const item of arr) {
// if(item === 2) {
// // break;
// continue;
// }
// console.log(item);
// }
// 3.在for...of中取得数组的索引
// const arr = [1,2,3];
// console.log(arr.keys());
// for(const key of arr.keys()) {
// console.log(key);
// }
//values()得到的是值的可遍历对象,可以遍历出值
// for(const value of arr.values()) {
// console.log(value);
// }
// entries()得到的是索引+值组成的数组的可遍历对象
// for(const entries of arr.entries()) {
// console.log(entries);
// }
13-5 原生可遍历与非原生可遍历
// 1. 什么是可遍历
// 只要有Symbol.iterator方法,并且这个方法可以生成可遍历对象,就是可遍历的
// 只要可遍历,就可以使用for...of循环来统一遍历
// 2.原生可遍历的有哪些
// 数组
// 字符串
// Set
// Map
// arguments
// NodeList
// for(const item of new Set([1,2,3])) {
// console.log(item);
// }
// 3.非原生可遍历的有哪些
// 一般的对象
// const person = {sex:'male',age:18};
// console.log(person[Symbol.iterator]());
// person[Symbol.iterator] = () => {
// let index = 0;
// return {
// next(){
// index++;
// if(index === 1) {
// return {
// value:person.age,
// done:false
// };
// } else if(index === 2) {
// return {
// value:person.sex,
// done:false
// }
// } else {
// return {
// done:true
// }
// }
// }
// }
// }
// for (const item of person) {
// console.log(item);
// }
// 有length和索引属性的对象
// const obj = {
// 0:'alex',
// 1:'male',
// length:2
// };
// obj[Symbol.iterator] = Array.prototype[Symbol.iterator]
// obj[Symbol.iterator] = () => {
// let index = 0;
// return {
// next() {
// let value,done;
// if(index <obj.length) {
// value = obj[index];
// done = false;
// } else {
// value = undefined;
// done = true;
// }
// index++;
// return {
// value,
// done
// };
// }
// };
// };
// for(const item of obj) {
// console.log(item);
// }
13-6 使用Iterator的场合
// 原生可遍历的
// Array数组
// String字符串
// Set
// Map
// 函数的arguments对象
// NodeList对象
// for...of
//1. 数组的展开运算符
// console.log(...[1,2,3]);
// console.log(...'str');
// console.log({...{}});
// //2. 数组的解构赋值
// [a,b] = [1,2,3];
// [a,b] = 'h1';
//3.Set和Map的构造函数
// new Set(ierator);
// new Map(iterator)
十四 字符串的新增方法
14-1 includes()
//1.基本用法
// console.log('abc'.includes('ab'));
// console.log('abc'.includes('ac')); //false
// //2. 第二个参数
// // 表示开始搜索的位置,默认是0
// console.log('abc',includes('a'));
// console.log('abc',includes('a',0));
// console.log('abc',includes('a',1)); //false
//3.应用
// https://www.imooc.com/course/list
// let url = 'https://www.imooc.com/course/list';
// const addURLParam = (url,name,value) => {
// url += url.includes('?') ? '&' : '?';
// url += `${name}=${value}`;
// return url;
// }
// url = addURLParam(url,'c','fe');
// console.log(url);
14-2 padStart()和padEnd()
//补全字符串长度
//1. 基本用法
// console.log('x'.padStart(5,'ab'));
// console.log('x'.padEnd(5,'ab'));
// console.log('x'.padEnd(4,'ab'));
//2. 注意事项
// 原字符串的长度,等于或大于最大长度,不会消减原字符串,字符串补全不生效,返回原字符串
// console.log(('xxx'.padStart(10,'011')));
// console.log('abc'.padEnd(10,'0123456789'));
//如果省略第二个参数,默认使用空格补全长度
// console.log('x'.padStart(4));
// console.log('x'.padEnd(4));
//3. 应用
// 显示日期格式
// console.log('1'.padStart(2,0));
14-3 trimStart()和trimEnd()
//清除字符串的首尾空格,中间的空格不会清除
// 1.基本用法
// const s = ' a b c ';
// console.log(s);
// console.log(s.trimStart());
// console.log(s.trimEnd());
// console.log(s.trimLeft());
// console.log(s.trimRight());
// console.log(s.trim());
//2.应用
// const usernameInput = document.getElementById('username');
// const btn = document.getElementById('btn');
// btn.addEventListener(
// 'click',
// () => {
// console.log(usernameInput.value);
// //验证
// if(usernameInput.value.trim() !== '') {
// //可以提交
// console.log('可以提交');
// } else {
// //不能提交
// console.log('不能提交');
// }
// //手动提交
// },
// false
// )
十五 数组的新增方法
15-1 includes()
// 判断数组找那个是否含有某个成员的
//基本遵循严格相等( === ),但是对于NaN的判断与 === 不同,
// includes 认为NaN === NaN
// console.log([1,2,NaN].includes(NaN));
// console.log([1,2,3].includes(2));
// console.log([1,2,3].includes('2'));
// 第二个参数表示搜索的起始位置,默认值是0
// console.log([1,2,3].includes(2,2));
// 2.应用
// 去重
// [1,2,1];
// const arr = [];
// for(const item of [1,2,1]) {
// if(!arr.includes(item)) {
// arr.push(item)
// }
// }
// console.log(arr);
15-2 Array.from()
//将其他数据类型转成数组
//1.基本用法
// console.log(Array.from('str'));
//2. 哪些可以通过Array.from()转换成数组
//2.1 所有可遍历的
// 数组、字符串、set、map、nodeList、arguments
// console.log(Array.from(new Set([1,2,1])));
// console.log([...new Set([1,2,1])]);
//2.2 拥有length 属性的任意对象
// const obj = {
// length:3,
// '0':'a',
// '1':'b',
// name:'Alex',
// };
// console.log(Array.from(obj));
//3.第二个参数
//作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组
// console.log(
// [1,2].map((value) => {
// return value*2
// }
// ));
// console.log(Array.from('12',value => value * 2));
// console.log(Array.from('12').map(value => value*2));
// //4.第三个参数
// Array.from(
// '12',
// function () {
// console.log(this);
// },
// document
// )
15-3 find()和findIndex()
//find(): 找到满足条件的一个立即返回
//findIndex(): 找到满足条件的一个,立即返回索引
//1.基本用法
// console.log(
// [1,5,10,15].find((value,index,arr) => {
// // console.log(value,index,arr);
// return value>9
// })
// );
// console.log(
// [1,5,10,15].findIndex((value,index,arr) => {
// // console.log(value,index,arr);
// return value>9
// })
// );
//2. 应用
// const students = [
// {
// name:'张三',
// sex:'男',
// age:16
// },
// {
// name:'李四',
// sex:'女',
// age:22
// },
// {
// name:'王二麻子',
// sex:'男',
// age:32
// },
// ];
// console.log(students.find(value => value.sex === '女'));
// console.log(students.findIndex(value => value.sex === '女'));
对象的新增方法
16-1 Object.assign();
// 用来合并对象
//1.基本用法
// Object.assign(目标对象,源对象1,...)
// const apple = {
// color:'红色',
// shape:'圆形',
// taste:'甜'
// };
// const pen = {
// color:'黑色',
// shape:'圆柱形',
// use:'写字'
// }
//Object.assign 直接河滨到了第一个参数中,返回的就是合并后的对象
//可以合并多个对象
// console.log(Object.assign(apple,pen));
// console.log(apple,apple === Object.assign(apple,pen));
// console.log(Object.assign({},apple,pen));
// console.log({...apple,...pen});
//2.注意事项
//2.1 基本数据类型作为源对象
// 与对象的展开类似,先转换成对象,再合并
// console.log(Object.assign({},undefined));
// console.log(Object.assign({},null));
// console.log(Object.assign({},1));
// console.log(Object.assign({},true));
// console.log(Object.assign({},'str'));
//2.2同名属性的替换
//后面的直接覆盖前面的
// const apple = {
// color:['红色','黄色'],
// shape:'圆形',
// taste:'甜'
// };
// const pen = {
// color:'黑色',
// shape:'圆柱形',
// use:'写字'
// };
// console.log(Object.assign({},apple,pen));
// 3.应用
//合并默认参数和用户参数
// const logUser = userOptions=> {
// const DEFAULTS={
// username:'ZhangSan',
// age:0,
// sex:'male'
// };
// const options = Object.assign({},DEFAULTS,userOptions);
// console.log(options);
// }
// //logUser
// logUser()
16-2 Object.keys()、Object.values()、Object.entries()
//1. 基本用法
// const person = {
// name:'Alex',
// age:18
// }
// console.log(Object.keys(person));
// console.log(Object.values(person));
// console.log(Object.entries(person));
// //2. 与数组类似方法的区别
// console.log([1,2].keys());
// console.log([1,2].values());
// console.log([1,2].entries());
//数组的keys()、values()、entries()等方法是实例方法,返回的都是Iterator
//对象的Object.keys()、Object.values()、Object.entries
//()等方法时构造函数方法、返回的是数组
//3. 使用for...of循环遍历对象
// const person = {
// name:'Alex',
// age:18
// };
// for(const key of Object.keys(person)) {
// console.log(key);
// }
// for(const value of Object.values(person)) {
// console.log(value);
// }
// for(const entries of Object.entries(person)) {
// console.log(entries);
// }
//Object.keys()/valuess()/entires()并不能保证顺序一定是你看到的样子,
//这一点和for in 是一样的
十七 初始Promise
17-1 Promise是什么
//1. 认识Promise
// Promise是异步操作的一种解决方案
// 回调函数
// document.addEventListener(
// 'click',
// () => {
// console.log('这里是异步的');
// },
// false
// );
// console.log('这里是同步的');
//2. 什么时候使用Promise
// Promise一般用来解决层层嵌套的回调函数(回调低于 callback hell)的问题
17-2 Promise的状态
//1. 实例化构造函数生成实例对象
// console.log(Promise);
//Promise解决的不是回调函数,而是回调地狱
// const p = new Promise(() => {});
//2. Promise的状态
// const p = new Promise((resolve,reject) => {
// //Promise有3种状态,一开始是pending(未完成),
// //执行resolve,变成fulfilled(resolved),已成功
// // resolve();
// //执行reject,变成rejected,已失败
// Promise的状态一旦变化,就不会再改变了
// //pending -> fulfilled
// resolve({username:'alex'});
// //pending -> rejected
// reject();
// })
// //3.then 方法
// p.then(data =>{
// console.log('success',data);
// },
// ()=> {
// console.log('error');
// })
// console.log(p);
十八 实例方法
18-1 then()
//1.什么时候执行
//pending -> fulfilled时,执行then的第一个回调函数
//pending -> rejected时,执行then的第二个回调函数
//2.执行后的返回值
//then方法执行后返回一个新的Promise对象
// const p = new Promise((resolve,reject) => {
// resolve();
// });
// const p2 = p.then(
// () => {},
// () => {}
// )
// .then()
// .then()
//console.log(p,p2,p === p2);
//3.then方法返回的Promise对象的状态改变
// const p = new Promise((resolve,reject) => {
// // resolve();
// reject()
// });
// p.then(
// () => {
// console.log('success');
// },
// () => {
// console.log('err');
// // 在then的回调函数中,return后面的东西,会用Promise包装一下
// // return undefined;
// //等价于
// // return new Promise((resolve,reject) => {
// // resolve(123);
// // })
// // 默认返回的永远都是成功状态的Promise对象
// return new Promise((resolve,reject) => {
// reject('reason')
// })
// }
// )
// .then(
// () => {
// console.log('success2');
// },
// (err) => {
// console.log('err2',err);
// }
// )
18-2 Promise解决回调地狱
<div id="box"></div>
<script>
const move = (el,{x = 0,y = 0} ={},end = ()=>{}) => {
el.style.transform = `translate3d(${x}px,${y}px,0)`
el.addEventListener(
'transitionend',
() => {
end();
},
false
)
}
const movePromise = (el,point) => {
return new Promise(resolve => {
move(el,point,() => {
resolve();
})
})
}
const boxEI = document.getElementById('box');
// document.addEventListener(
// 'click',
// () => {
// move(boxEI,{x:150},() => {
// move(boxEI,{x:150,y:150},()=> {
// move(boxEI,{y:150},()=> {
// move(boxEI,{x:0,y:0})
// })
// })
// })
// }
// )
document.addEventListener(
'click',
() => {
movePromise(boxEI,{x:150}).then(() => {
return movePromise(boxEI,{x:150,y:150})
}).then(() => {
return movePromise(boxEI,{y:150});
}).then(() => {
return movePromise(boxEI,{x:0,y:0})
})
},
false
)
</script>
18-3 catch()
<script>
// 1.有什么用
// then(
// data => {},
// ett => {}
// )
// then(data => {});
//catch专门用来处理reject状态
//catch本质上是then的特例
// then(null,err=>{});
//2. 基本用法
new Promise ((resolve,reject) => {
// resolve(123)
reject('reason');
})
// .then(data => {
// console.log(data);
// })
// .then(null,err=> {
// console.log(err);
// })
.catch(err => {
console.log(err);
//return undefined
}).then(data => {
console.log(data);
});
//catch()可以捕获它前面的错误
//一般总是建议,Promise对象后面要跟catch方法,这样可以处理
//Promise内部发生的错误
</script>
十九 构造函数方法
19-1 Promise,resolve()和Promise.reject()
<script>
// 1.Promise.resolve()
// 是成功状态Promise的一种简写形式
// new Promise(resolve => resolve('foo'))
//简写
//Promise.resolve('foo')
//参数
//一般参数
// Promise.resolve('foo').then(data=>{
// console.log(data);
// });
//Promise
//当Promise.resolve()接收的是Promise对象时,直接返回这个Promise对象,什么都不做
// const p1 = new Promise(resolve => {
// setTimeout(resolve,1000,'我被执行了');
// // setTimeout(()=> {
// // resolve('我被执行了')
// // },1000)
// })
// Promise.resolve(p1).then(data => {
// console.log(data);
// })
// //等价于
// p1.then(data => {
// console.log(data);
// });
// console.log(Promise.resolve(p1) === p1);
//当resolve函数接收的是Promise对象时,后面的then会根据传递的Promise对象的状态变化决定执行哪一个回调
// new Promise(resolve => resolve(p1)).then(data => {
// console.log(data);
// });
// 具有then方法的对象
// const thenable = {
// then(resolve,reject) {
// console.log('then');
// resolve('data');
// // reject('reason')
// }
// }
// Promise.resolve(thenable).then(
// data => console.log(data),
// err => console.log(err)
// );
//2. Promise.reject()
//失败状态Promise的一种简写形式
// new Promise((resolve,reject) => {
// reject('reason')
// });
//等价于
//Promise.reject('reason');
//参数
//不管什么参数,都会原封不动地向后传递,作为后续方法的参数
// const p1 = new Promise(resolve => {
// setTimeout(resolve,1000,'我被执行了');
// })
// Promise.reject(p1).catch(err => {
// console.log(err);
// })
new Promise((resolve,reject) => {
resolve(123)
})
.then(data => {
console.log(data);
})
.then(data => {
console.log(data);
})
.catch(err => console.log(err))
</script>
19-2 Promise.all()
<script>
//1. 有什么用
//Promise.all()关注多个Promise对象的状态变化
//传入多个Promise实例,包装成一个新的Promise实例返回
//2. 基本用法
const delay = ms => {
return new Promise(resolve => {
setTimeout(resolve,ms)
})
}
const p1 = delay(1000).then(() => {
console.log('p1 完成了');
// return 'p1'
return Promise.reject('reason')
});
const p2 = delay(2000).then(() => {
console.log('p2 完成了');
return 'p2'
})
//Promise.all()的状态变化与所有传入的Promise实例对象状态有关
//所有状态都编程resolved,最终的状态才会变成resolved
//只要有一个变成rejected,最终的状态就变成rejected
const p = Promise.all([p1,p2]);
p.then(data => {
console.log(data);
},
err => {
console.log(err);
}
)
</script>
19-3 Promise.race()和 Promise.allSettled()
<script>
//1.Promise.race()
const delay = ms => {
return new Promise(resolve => {
setTimeout(resolve,ms)
})
}
const p1 = delay(1000).then(() => {
console.log('p1 完成了');
return 'p1'
// return Promise.reject('reason')
});
const p2 = delay(2000).then(() => {
console.log('p2 完成了');
return 'p2'
})
//Promise.race()的状态取决于第一个完成的Promise实例对象,
//如果第一个完成的成功了,那最终的就成功;如果第一个完成的失败了,那最终的就失败
// const racePromise = Promise.race([p1,p2]);
// racePromise.then(
// data => {
// console.log(data);
// },
// err => {
// console.log(err);
// }
// )
//2.Promise.allSettled()
//Promise.allSettled()的状态与传入的Promise状态无关
//永远都是成功的
//它只会忠实的记录下各个Promise的表现
const allSettledPromise = Promise.allSettled([p1,p2]);
allSettledPromise.then(
data => {
console.log('succ',data);
},
err => {
console.log(err);
}
)
</script>
二十 注意事项和应用
20-1 Promise的注意事项
<script>
//1.resolve或reject函数执行后的代码
new Promise((resolve,reject) => {
// reject('reason');
// console.log('hi');
})
//2.Promise.all/race/allSettled的参数问题
//参数如果不是Promise数组,会将不是Promise的数组元素转变成Promise对象
//Promise.all([1,2,3]).then(datas => {
// console.log(datas);
//})
// 等价于
// Promise.all([
// Promise.resolve(1),
// Promise.resolve(2),
// Promise.resolve(3)
// ]).then(datas => {
// console.log(datas);
// })
//不只是数组,任何可遍历的都可以作为参数
//数组、字符串、Set、Map、NodeList、arguments
// Promise.all(new Set([1,2,3])).then(datas => {
// console.log(datas);
// })
//3.Promise.all/race/allSettled的错误处理
const delay = ms => {
return new Promise(resolve => {
setTimeout(resolve,ms)
})
}
const p1 = delay(1000).then(() => {
console.log('p1 完成了');
// return 'p1'
return Promise.reject('reason')
})
.catch(err => {
console.log('p1',err);
})
const p2 = delay(2000).then(() => {
console.log('p2 完成了');
return 'p2'
})
const allPromise = Promise.all([p1,p2]);
allPromise.then(datas => {
console.log(datas);
}).catch(err => {
console.log(err);
})
//错误既可以单独处理,也可以统一处理
//一旦被处理,就不会在其他地方再处理一遍
</script>
20-2 Promise的应用
<img src="https://img.mukewang.com/5e6af63d00011da31872076.jpg" alt="图片返回异常" id="img">
<script>
//1. 异步加载图片
const loadImgAsync = url =>{
return new Promise((resolve,reject)=> {
const img = new Image();
img.onload = ()=> {
resolve(img)
};
img.onerror = () => {
reject(new Error(`Could not load image at ${url}`))
}
img.src = url;
})
}
const imgDOM = document.getElementById('img')
loadImgAsync('https://img.mukewang.com/5f057a6a0001f4f918720764.jpg').then(
img => {
console.log(img.src);
setTimeout (() => {
imgDOM.src = img.src
},1000)
}
).catch(err => {
console.log(err);
}
)
</script>
二十一 初识Class
21-1 Class是什么
<script>
// 1.认识Class
// 人类:类
// 具体的人:实例、对象
//类可以看做是对象的模板,用一个类可以创建出许多不同的对象
//2.Class的基本用法
// 类名一般首字母大写
// class Person {} {} x
class Person {
//实例化时执行构造方法,所有必须有构造方法,但可以不写出来
construtor(name,age) {
this.name = name;
this.age = age
//一般在构造方法中定义属性,方法不在构造方法中定义
// this.speak = ()=>{};
}
//各实例共享的方法
speak(){
console.log('speak');
}
}
// Person()
const p = new Person('ZS',18);
p.speak()
</script>
21-2 Class的两种定义方式
<script>
//1. 声明形式
// class Person {
// constructor() {}
// speak(){}
// }
//2.表达式形式
// function Person(){}
// const Person = function () {};
const Person = class {
constructor() {
console.log('construtor');
}
speak() {
};
}
new Person();
(function () {
console.log('func');
})()
//立即执行的类
new (class {
constructor() {
console.log('construtor');
}
})()
</script>
二十二 属性与方法
22-1 实例属性、静态方法、静态属性
<script>
//1. 实例属性
// class Person {
// age = 18
// sex = 'male'
// getSex = function () {
// return this.sex;
// }
// constructor (name,sex) {
// this.name = name;
// this.sex = sex;
// }
// }
// const p = new Person('Alex');
// console.log(p.name);
//2.静态方法
//类的方法
// class Person {
// constructor (name,sex) {
// this.name = name;
// this.sex = sex;
// }
// speak() {
// console.log('speak');
// console.log(this);
// }
// static speak() {
// console.log('static speak');
// //this指向类
// console.log(this);
// }
// }
// const p = new Person('Alex');
// p.speak();
// Person.speak();
//3. 静态属性
// 类的属性
class Person {
constructor (name) {
this.name = name;
}
//不要这么写,目前只是题案,有兼容性问题
// static version='1.0'
static getVersion() {
return '1.0'
}
}
// Person.version = '1.0'
const p = new Person('Alex');
console.log(p.name);
// console.log(Person.version);
console.log(Person.getVersion());
</script>
22-2 私有属性和方法
<script>
//1.为什么需要私有属性和方法
//一般情况下,类的属性和方法都是公开的
//公有的属性和方法可以被外界修改,造成意想不到的错误
// class Person {
// constructor (name) {
// this.name = name;
// }
// speak() {
// console.log('speak');
// }
// getName() {
// return this.name;
// }
// }
// const p = new Person('Alex');
// console.log(p.name);
// p.speak();
//...
// p.name = 'zs';
//2.模拟私有属性和方法
//2-1._开头表示私有
// class Person {
// constructor (name) {
// this._name = name;
// }
// speak() {
// console.log('speak');
// }
// getName() {
// return this._name;
// }
// }
// const p = new Person('Alex');
// console.log(p.name);
// console.log(p.getName());
//2.2 将私有属性和方法移出类
(function() {
let name = ''
class Person {
constructor (username) {
name = username;
}
getName() {
return name
}
}
window.Person = Person;
})();
(function () {
const p = new Person('Alex');
console.log(p.getName());
})();
</script>
二十三 继承
23-1 extends
<script>
//1. 子类继承父类
class Person {
constructor(name,sex) {
this.name = name;
this.sex = sex;
this.say = function () {
console.log('say');
}
}
static speak () {
console.log('static speak');
}
}
// Person.version = '1.0';
// class Programmer extends Person {
// constructor(name,sex){
// super(name,sex)
// }
// }
// const zs = new Programmer('zs','男')
// console.log(zs.name);
// console.log(zs.sex);
// zs.say();
// Programmer.speak();
//2.改写继承的属性或方法
class Programmer extends Person {
constructor(name,sex,feature){
super(name,sex)
this.feature = feature
}
//同名覆盖
speak() {
console.log('Programmer speak');
}
static speak() {
console.log('Programmer static speak');
}
}
const zs = new Programmer('zs','男','秃头')
console.log(zs.name);
console.log(zs.feature);
zs.say();
Programmer.speak();
</script>
23-2 super
<script>
//1.作为函数调用
//代表父类的构造方法,只能在子类的构造方法中,用在其他地方就会报错
//super虽然代表了父类的构造方法,但是内部的this指向子类的实例
// class Person {
// constructor(name) {
// this.name = name;
// console.log(this);
// }
// }
// class Programmer extends Person {
// constructor(name,sex) {
// super(name,sex);
// }
// }
// // new Person();
// new Programmer();
//2.作为对象使用
//2.1 作为构造方法使用或一般方法中使用
// super代表父类的原型对象 Person.prototype
// 所以定义在父类实例上的方法或属性,是无法通过super调用的
//通过super调用父类的方法时,方法内部的this指向当前的子类实例
// class Person {
// constructor(name) {
// this.name = name;
// console.log(this);
// }
// speak() {
// console.log('speak');
// console.log(this);
// }
// static speak() {
// console.log('static speak');
// console.log(this);
// }
// }
// class Programmer extends Person {
// constructor(name,sex) {
// super(name,sex);
// // console.log(super.name);
// // super.speak()
// }
// speak() {
// super.speak();
// console.log(('Programmer speak'));
// }
// //2.2 在静态方法中使用
// // 指向父类,而不是父类的原型对象
// // 通过super调用父类的方法时,方法内部的this指向当前的子类,而不是子类的实例
// static speak() {
// super.speak();
// console.log('Programmer speak');
// }
// }
// // new Person()
// // new Programmer()
// Programmer.speak()
//3.注意事项
// 使用super的时候,必须显式指定是作为函数还是作为对象使用,否则会报错
class Person {
constructor(name) {
this.name = name;
}
speak() {
console.log('speak');
console.log(this);
}
}
class Programmer extends Person {
constructor(name,sex) {
super(name,sex);
// console.log(super);
console.log(super.speak);
console.log(super());
}
}
</script>
二十五、 初识Module
25-1 Module是什么
1. 什么是模块
模块:一个一个的局部作用域的代码块
2. 什么是模块系统
模块系统需要解决的主要问题
- ①模块化的问题
- ②消除全局变量
- ③管理加载顺序
RequireJS seaJS
ES Module
25-2 Module的基本用法
1. 使用Module模块化之前的例子
2. 使用script标签加载模块
一个文件就是一个模块
只要你会用到import或export,在使用script标签加载的时候,就要加上type='module'
3. 分析Module解决问题
二十六、导入与导出
26-1 Module的两种导出和导入
1. 认识导出和导入
导出的东西可以被导入(import),并访问到
一个模块没有导出,也可以将其导入
被导入的代码都会执行一遍,也仅会执行一遍
import './js模块/module.js'
2. 基本用法
可以随便起名
import age from './js模块/module.js';
console.log(age);
一个模块只能有一个export default
26-2 export和对应的import
// js模块部分
html部分
二十七、注意事项与应用
27-1 Module的注意事项
js模块部分
html部分
二十八、Babel
28-1 Babel是什么
1. 认识Babel
官网:babeljs.io/
在线编译:babeljs.io/repl
Babel 是JavaScript的编译器,用来将es6的代码,转换成es6之前的代码
2. 使用Babel
Babel本身可以编译ES6的大部分语法,比如let、const、箭头函数、类
但是对于ES6新增的API,比如Set、Map、Promise等全局对象,以及一些定义在全局对象上的方法(比如Object.assign/Array.from)都不能直接编译,需要借助其他的模块
Babel一般需要配合Webpack来编译模块语法
28-3 使用Babel前的准备工作
1. 什么是Node.js 和 npm
Node.js是个平台或者工具,对应浏览器
后端的JavaScript = ECMAscript + IO + File + ...等服务器端的操作
npm: node包管理工具
2. 安装Node.js
node -v npm -v
3.初始化项目
npm init -> package.json
4. 安装Babel需要的包
npm config set registry registry.npm.taobao.org
npm install --save-dev @babel/core @babel/cli
npm install (如果不写包名会自动找同文件的package文件下载里面记录的)
28-4 使用Babel编译ES6代码
1. 执行编译的命令
在package.json 文件中添加执行babel的命令
babel src -d dist
babel src --out-dir dist
2. Babel的配置文件
.babelrc
npm install @babel/preset-env@7.11.0 --save-dev
创建配置文件 .babelrc,并配置
{
"presets":["@babel/preset-env"]
}
二十九 Webpack入门
29-1 Webpack是什么
1. 认识Webpack
webpack是静态模块打包器,当webpack处理应用程序时,会将所有这些模块打包成一个或多个文件
//import'./module.js'
//require('./module.js')
2. 什么是Webpack
模块
webpack可以处理js/css/图片、图标字体等单位
静态
开发过程中存在于本地的js/css/图片/图标字体等文件,就是静态的
动态的内容,webpack没办法处理,只能处理静态的
29-2 Webpack初体验
1. 初始化项目
npm init
2. 安装Webpack需要的包
npm install --save-dev webpack-cli@3.3.12 webpack@4.44.1
3. 配置Webpack
webpack.config.js
4.编译并测试
三十 Webpack的核心概念
30-1 Webpack的4个核心理念
entry和output
30-2 loader
1.什么是loader
webpack js/css/图片
loader 让Webpack能够去处理那些非JS文件的模块
babel
2. babel-loader
npm install --save-dev babel-loader@8.1.0 @babel/core@7.11.0 @babel/preset-env@7.11.0