let关键字与const关键字
主要作用:声明变量
let命令
与var
的相似,都是声明变量的。var
有变量提升,let
和const
没有
let没有变量提升
脚本编译的时候看到,var
声明的变量会提到上面先声明
console.log(a);
var a=10
//等同于
var a
console.log(a)
a=10;
let是一个块级作用域
if(1===1){
let a=10;
console.log(a)
}
console.log(a);
在代码块外部打印不出来,并且抛出错误。
let不能重复声明
let a=10;
let a=20;
console.log(a)
var
可以重复声明,let
则不能重复声明变量
const命令
const
和var
、let
作用也是相似的都是声明变量的
const
也是一个块级作用域,也没有变量提升,也不能重复声明
const max = 30;
console.log(max)
const max= 40;
console.log(max)
与
let
和var
的不同是:const
一般都是声明常量一旦修改无法改变。
const max = 30;
console.log(max)
max= 40;
console.log(max)
一般框架里面作者使用
const
来声明常量,这样使用者使用的时候将无法修改里面的常量。
const
可以声明对象形式的常量,但是不能直接修改常量对象,但是可以修改常量中的内部属性
可以修改常量中的内部属性
const person={
name:"小太阳"
}
console.log(person);
person.name="小胖子";
console.log(person);
不能直接修改常量对象
const person={
name:"小太阳"
}
console.log(person);
person.name="小胖子";
console.log(person);
const person={
name="小胖子"
}
console.log(person);
const和let的作用
使用更灵活
使用let
和const
在for
循环中如果想拿到第5次循环的结果就能拿到第5次循环的结果,在var
中则是把for
循环执行完然后返回最终结果
for循环是个经典案例
const arr=[];
for(let i=0;i<10;i++){
arr[i]=function(){
return i;
}
}
console.log(arr[5]());//5
var arr=[];
for(var i=0;i<10;i++){
arr[i]=function(){
return i;
}
}
console.log(arr[5]()); //10
使用let不会对全局造成污染
let RegExp=10;
console.log(RegExp)
console.log(window.RegExp);
window
有一个RegExp
函数,我声明的不会影响全局属性
一般情况下使用const,只有在知道变量需要修改的时候使用let。
模板字符串。
模板字符串就是Tab键上面的反引号,把结构包裹起来,哪里需要变量就通过${}把当前变量名插入到结构里面就可以了。
<div class="box"></div>
JS原始的字符串拼接
const oBox=document.querySelector(".box");
let id=1;
name="小太阳";
oBox.innerHTML="<ul><li><p id="+id+">"+name+"</p></li></ul>"
使用模板字符串拼接
const oBox=document.querySelector(".box");
let id=1;
name="小太阳";
let htmlStr=`<ul>
<li>
<p id=${id}>${name}</p>
</li>
</ul>`
oBox.innerHTML=htmlStr
函数默认值
在ES5中函数调用的时候有形参,但是没有传入实参,那么就要给形参一个默认值。
function add(a, b) {
a = a || 10; //a有值就赋值给a,a没值就默认10
b = b || 20;
return a + b;
}
console.log(add()) //30
在ES6中
传值了就走你传的参数,你没传参数那么就走原来的
function add(a,b=5){
return a+b;
}
console.log(add(10,20)) //30
默认的表达式也可以是个函数
function add(a,b=getVal(5)){
return a+b;
}
function getVal(val){
return val+5;
}
console.log(add(10))
剩余参数
收集剩余的参数,由三个点...和一个紧更着的具名参数指定。(...keys),如果放在函数的形参中必须放在后面。
和arguments
不同的是,剩余参数返回真实数组,arguments
返回伪数组
function checkArgs(...keys){
console.log(keys);
console.log(arguments)
}
checkArgs("a","b","c")
扩展运算符
扩展运算符也是三个点,它和剩余参数不同的是
剩余参数是:把多个独立的参数合并到一个数组中 扩展运算符:将一个数组分割,并将各个项作为分离的参数传递给函数
在ES5中用apply
来传递参数,代码相对于比较麻烦
var arr=[10,23,45,65,47,98,24]
console.log(Math.max.apply(null,arr)) //98
扩展运算符是将数组分割,传入Math.max
中逐一比较然后返回最大值
var arr=[10,23,45,65,47,98,24]
console.log(Math.max(...arr)) //98
箭头函数(重要)
函数的简写
使用=>来定义,取缔了ES5中function(){}
的方式来定义函数,等价于()=>(){}
。让代码更加简洁
原始写法
let add=function(a,b){
return a+b
}
console.log(add(10,20)) //30
ES6的写法
let add=(a,b)=>{
return a+b
}
console.log(add(10,20)) //30
//等价于
let add=(a,b)=>(a+b); //(a+b)表示return返回的值
console.log(add(10,20)) //30
箭头函数中this的指向
在ES6中是没有this
绑定的。箭头函数内部this
只能通过查找作用域链来确定。如果使用箭头函数就不会发生this
指向错误的问题。
在ES5中this
的指向取决于调用该函数的上下文对象。ES5中this会发生指向错误的现象
let pageHandle={
id:123,
init:function(){
document.addEventListener("click",function(event){
console.log(this)
this.doSomeThings(event.type)
})
},
doSomeThings:function(type){
console.log(`事件类型:+${type},当前ID:+{this.id}`)
}
}
pageHandle.init()
上文给文档添加了
click
事件,当调用函数的时候,内部this
就指向了定义函数时候的上下文document
。所以这时候this
发生了改变。
箭头函数是没有this
指向的,箭头函数中内部的this
,只能通过查找作用域链来进行确定。一旦使用了箭头函数,它只寻找当前对象。
let pageHandle={
id:123,
init:function(){
document.addEventListener("click",event=>{
console.log(this)
this.doSomeThings(event.type)
},false)
},
doSomeThings:function(type){
console.log(`事件类型:+${type},当前ID:+{this.id}`)
}
}
pageHandle.init()
注意:给每个方法一定不要使用箭头函数,不然会把
this
指向最外层作用域window
。比如上文的init
方法不能使用箭头函数。
使用箭头函数注意事项
1. 使用箭头函数的时候内部就不存在arguments
。
let getVal=(a,b)=>{
console.log(arguments);
return a+b;
}
console.log(getVal(2,3))
2. 箭头函数不能使用new关键字来实例化对象
function
是一个对象,但是箭头函数不是一个对象,箭头函数相当于函数的语法糖
let getVal=()=>{}
let p=new getVal()
console.log(p)
此处代码不会认为箭头函数它是一个
function
作用域,所以就没constructor
属性,所以不是一个构造函数
解构赋值
解构赋值是对赋值运算符的一种扩展。通常它是针对数组或者对象来进行操作。
优点:书写简单易读
对象解构
对象完全解构
let node={
type:"iden",
name:"foo"
}
let {type,name}=node;
console.log(type,name) //iden foo
不完全解构,有的属性可忽略。
let node={
type:"iden",
a:{
name:"小太阳"
},
b:[]
}
let {a}=node;
console.log(a)
剩余运算符解构
let node={
type:"iden",
a:{
name:"小太阳"
},
b:[]
}
let {a,...res}=node;
console.log(a,res)
数组解构
数组完全解构
let arr=[1,2,3]
let [a,b,c]=arr
console.log(a,b,c) //1,2,3
数组不完全解构
let arr=[1,2,3]
let [a,b]=arr
console.log(a,b) //1 2
数组嵌套解构
let [a,[b],c]=[1,[2],3]
console.log(a,b,c)
扩展的对象的功能
ES6可以直接写入变量和函数,作为对象的属性和方法
const name="小太阳";
age=20;
const person={
name, //等价于name:name
age,
sayName(){
console.log(this.name) //小太阳
}
}
person.sayName()
对象的方法
is 等价于三个等号(===)特殊情况下使用
比较两个值是否严格相等,既比较值又比较数据类型。解决了在===
下出现的不严谨现象
在三个等号下:不严谨
console.log(NaN===NaN) //false
在is下就会严格相等
console.log(Object.is(NaN,NaN)) //true
assign() 主要是浅拷贝
用于一个对象的合并,返回合并之后的新对象
let newObj=Object.assign({},{a:1},{b:2},{c:3});
console.log(newObj)
Symbol类型
Symbol是一种原始数据类型,一旦使用symbol声明了值,它表示是独一无二的值。
const name=Symbol("name");
const name2=Symbol("name");
console.log(name===name2) //false
最大的用途就是用来定义对象的私有变量
通过Symbol
声明出来的变量名是一个独一无二的值,声明出来属性名之后可以做为对象属性表示它是独一无二的,然后变成对象的私有属性。
let s1=Symbol("小太阳");
console.log(s1);
let obj={}
obj[s1]="小胖子",
console.log(obj) //Symbol(小太阳): "小胖子"
console.log(obj[s1]) //获取值 小胖子
//简写
let s1=Symbol("小太阳");
console.log(s1);
let obj={
[s1]:"小胖子" //这里一定是[变量名]
}
console.log(obj) //Symbol(小太阳): "小胖子"
console.log(obj[s1]) //小胖子 获取值
声明一个
obj
对象,给obj
对象赋值一个s1
,此处的s1
就是obj
的私有变量。使用Symbol
来定义对象中的变量,取值的时候一定要用中括号来取值[变量名]
Set
Set表示一个集合,表示无重复值的有序列表
let ste=new Set();
ste.add(2)
ste.add("3")
ste.add([1,2,3])
console.log(ste)
ste.delete(2); //删除元素
console.log(ste);
//校验数组中是否有这个元素,如果有就返回true,否则返回false
console.log(ste.has("4"))
console.log(ste.size) //检测数组的长度
将set转化成一个数组可使用扩展运算符
let arr=new Set([1,2,3,4,5,5,6])
let arr1=[...arr]
console.log(arr1)
Set中对象的引用无法释放
解决办法就是什么变量的时候不使用Set
而是使用WeakSet
释放前的代码
let set=new Set(),obj={};
set.add(obj);
obj=null;
console.log(set)
释放后的代码没有size
属性,__propo__
里面也少了很多方法
let set=new WeakSet(),obj={};
set.add(obj);
obj=null;
console.log(set)
WeakSet与Set的不同
- 不能传入非对象类型的参数
- 不可迭代
- 没有forEach方法
- 没有size属性
Map
Map是一个键值对的有序列表,它的键和值可以是任意类型
let map =new Map();
map.set("name","张三");
map.set("age",20);
console.log(map); //Map(2) {"name" => "张三", "age" => 20}
console.log(map.get("name")) //取name的值 张三
console.log(map.has("name")) //校验map中是否有name true
map.delete("name") //删除name
console.log(map.has("name")) //校验map中是否有name false
map.set(["a",[1,2,3]],"hello") //可以传入不同类型的值
console.log(map)
数组from方法与of方法
from方法
将伪数组转为真的数组
function add(){
let arr=Array.from(arguments)
console.log(arr)
}
add(1,2,3,4,5)
通过扩展运算符将伪数组转为真正的数组
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
let arr=document.querySelectorAll("li")
console.log([...arr])
</script>
from还可以接收第二个参数,用来对每个元素进行处理
let lis=document.querySelectorAll("li")
//ele.textContent获取li标签中的内容返回给arr
let arr=Array.from(lis,ele=>ele.textContent)
console.log(arr)
of方法
of方法是将任意的数据类型转换到数组
console.log(Array.of([1,2,3,4],3,4,"3","4",{a:2}))
copywithin方法
copywithin
方法将数组内部将指定位置的元素复制到其他位置,并返回当前新数组
console.log([1,2,3,4,5,6].copyWithin(0,3)) //[4, 5, 6, 4, 5, 6]
从索引为3向后的数组复制到从索引为0开始后面的3个数值
find方法 查找元素
找出第一个符合条件的元素
let number=[1,2,-4,-5].find(n=>n<0) //箭头函数的缩写
console.log(number) //-4
findIndex方法 查找索引
找出第一个符合条件的元素的索引
let number=[1,2,-4,-5].findIndex(n=>n<0)
console.log(number) //2
entries() keys() values()返回一个遍历器,可以使用for...of循环遍历
keys()
使用keys()
返回一个Array Iterator {}
遍历器
console.log(["a","b"].keys())
使用
for...of
就能把当前遍历器的索引给遍历出来
for(let index of ["a","b","c","d"].keys()){
console.log(index);
}
values()
使用values()
返回一个Array Iterator {}
遍历器
console.log(["a","b","c"].values())
使用
for...of
就能把当前遍历器的值给遍历出来
for(let index of ["a","b","c","d"].values()){
console.log(index);
}
entries()
使用entries()
返回一个Array Iterator {}
遍历器
console.log(["a","b","c","d"].entries()); //Array Iterator {}
使用for...of
遍历出当前数组的键值对取出来
for(let [index,ele] of ["a","b","c","d"].entries()){
console.log(index,ele);
}
includes()
includes
返回一个布尔值,表示某个数组是否包含给定的值,可以替代indexOf
console.log(["a","b","c","d"].includes("a")); //返回布尔值true
相似与于indexOf
,indexOf
如果有包含的值则返回出对应值的索引继续执行代码,如果没有则返回-1终止接下来代码的执行。
console.log(["a","b","c","d"].indexOf("c")); //返回C对应的索引 2
迭代器iterator
- 迭代器是一个统一的接口,作用是使各种数据结构可以快捷的访问。通过
Symbol.iterator
来创建迭代器,使用next()来获取迭代过后的结果,返回值返回一个函数。返回值一个是value
,一个是done
,done
表示是否完成,整个遍历完成返回true
,否则返回false
遍历继续执行 - 迭代器是一个遍历数据结构的指针
//使用迭代器
const items=["one","two","therr"]
// 创建新的迭代器
const ite=items[Symbol.iterator]();
console.log(ite.next()); //{value: "one", done: false}
console.log(ite.next()); //{value: "two", done: false}
console.log(ite.next()); //{value: "therr", done: false}
console.log(ite.next()); //{value: undefined, done: true}
是一种新的遍历机制。使用迭代器,当然迭代就是遍历,遍历就是迭代
生成器generator
generator
函数可以通过yield
关键字将函数挂起,(挂起的意思是指将函数停留在这里不再继续执行),为了改变执行流提供了可能,同时为了做异步编程提供了方案
和普通函数的区别:
- 在
function
后面于函数名前面有一个*
号就表示是一个生成器函数。 - 只能在函数内部使用
yield
表达式,将函数挂起来(停留)
function* func() {
console.log("one"); //one
yield 1;
}
let fen = func()
console.log(fen); //func {<suspended>}
console.log(fen.next()) //{value: 1, done: false}
函数返回一个对象,里面有一个next
方法,调用方法的时候执行函数,直到遇见return
,如果没有return
则继续执行直到代码执行完毕。否则停留在当前yield
语句。
总结:generator是分段执行的,yield语句是暂停执行,而next方法是恢复执行(当碰到yield的时候代码就卡在当前位置,调用next方法的时候就会把结果返回出来,一个next对应一个yield)
next方法可以传参
function* func() {
console.log("one:"); //one:
//x不是yield的返回值,它是next方法恢复当前yield执行函数的实参。
let x=yield 9;
console.log("two:"+x); //two:5
let y=yield 2;
console.log("three:"+y) //three:6
return x+y
}
let fen = func()
console.log(fen.next(4)) //{value: 9, done: false}
console.log(fen.next(5)) //{value: 2, done: false}
console.log(fen.next(6)) //{value: 11, done: true}
作用:为不具备Iterator
接口的对象提供遍历操作。
生成器generator的应用
解决回到地狱繁琐的问题
回调地狱:ajax
请求的时候有时候会函数套函数,一个请求里面有无限级ajax
请求。代码繁琐。这时候就可以使用生成器将异步代码同步化。
function* main(){
console.log('main');
let res = yield request('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976')
console.log(res);
// 执行后面的操作
console.log('数据请求完成,可以继续操作');
}
const ite = main();
ite.next();
function request(url){
$.ajax({
url,
method:'get',
success(res){
ite.next(res);
}
})
}
在项目开发中也会遇到loading...
的加载中、loading...
数据加载完成,loading...
隐藏的需求,但是数据加载完成之前是需要时间的,要是数据过大,加载延迟,就会出现先执行隐藏阶段,后加载loading
数据完成。
function loadUI(){
console.log("loading...加载中")
}
function showData(){
setTimeout(()=>{
console.log("loading...数据加载完成")
},1000)
}
function hideUI(){
console.log("隐藏loading...页面")
}
loadUI();
showData();
hideUI();
Generator可以部署AJAX操作。生成器可以让异步代码同步化
// 构造一个生成器
function *load(){
loadUI();
// 要把showData卡在当前位置,让我执行完了再继续执行隐藏的步骤
yield showData();
hideUI();
}
// 创建迭代器
let itLoad=load();
// 第一次调用next 执行showData
itLoad.next();
function loadUI(){
console.log("loading...加载中")
}
function showData(){
// 模拟异步的状态
setTimeout(()=>{
//异步操作完成之后才继续执行next激活hideUI函数
console.log("loading...数据加载完成")
// 通过迭代器调用next,继续往下执行隐藏loading...页面
itLoad.next()
},1000)
}
function hideUI(){
console.log("隐藏loading...页面")
}
- 语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。
- Generator 函数除了状态机,还是一个遍历器对象生成函数。 可暂停函数, yield可暂停,next方法可启动,每次返回的是yield后的表达式结果。
- yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
Promise对象
在ES6中给我们提供了三种对于异步编程的解决方案:
- Generator与yield
- Promise对象
- async/await
Promise
就是承诺的意思,Promise
相当于一个容器,里面保存着一些未来才会结束的事件,通常未来才会结束的事件是一个异步结果。比如发送一个ajax
事件两秒钟才能将我的数据请求回来,那么这个时候就是一个将要结束的事件,在Promise
中就保存着事件结果。
Promise对象优势
各种异步操作都可以用同一种方法进行处理,比如axios
内部就是使用Promise
来实现的
Promise对象特点
具有两大特点
- 对象的状态不受外界影响,通常处理异步操作有三个状态,进行中
pending
、已完成Resolved
、失败Rejected
。不管外界传入什么都不会影响这三个状态。 - 一旦状态改变就不会再次发生改变。任何时候都可以得到这个结果
Promise基本用法
//1.创建一个Promise对象
//2.promise接收一个参数,这个参数是一个回调函数
//3.在回调函数中接收两个参数,一个是成功的(resolved),一个是失败的(rejected)
// 4.当new出这个实例过后会返回出一个promise对象
let pro=new Promise(function(resolved,rejected){ //resolved,rejected两个参数是两个函数
// 5.在这中间执行异步操作
// 加入从后端返回一个对象
let res={
code:201,
data:{
name:"小太阳"
},
error:"请求失败了"
}
// 一段时间之后我接收这个数据
setTimeout(()=>{
// 在这内部我可以去判断code是不是等于200,如果是就返回成功接收的数据data,失败返回error
if(res.code===200){
resolved(res.data)
}else{
rejected(res.error)
}
},1000)
})
// 用then接收执行完异步方法之后返回的状态,then 里面接收一个回调函数。
// 参数就是成功回调回来的结果
// pro.then里面不光可以接收一个回调函数还可以接收多个回调函数
pro.then((val)=>{
// 在这个回调函数内打印结果
console.log(val)
},(err)=>{
console.log(err)
})
基本使用是会了但是代码还是比较生硬,比如请求时间想通过调用的时候自己传进来,而不是里面写死了。
// 有一个函数timeOut,毫秒就是参数ms
function timeOut(ms){
// timeOut(2000)成功调用后返回去一个Promise对象
return new Promise((resolved,rejectad)=>{
setTimeout(()=>{
resolved("数据请求成功")
},ms)
})
}
// 在外界调用timeOut的时候把毫秒传过去如果成功了,然后执行then返回结果
timeOut(2000).then((val)=>{
console.log(val)
})
resolve方法
resolve方法能将一个现有的对象直接转成一个Promise对象,然后就有它自己的状态然后就可以通过.then
、.catch
来调用
let p=Promise.resolve("foo");
//等价于
let p=new Promise(resolve=>resolve("foo"));
p.then((data)=>{
console.log(data) //foo
})
reject
reject方法能将一个现有的对象直接转成一个Promise对象,然后就有它自己的状态然后就可以通过.then
、.catch
来调用
let p=new Promise(reject=>reject("foo"));
p.then((data)=>{
console.log(data) //foo
})
all方法
all方法是提供了并行的执行异步操作行为
let promise1=new Promise((resolve,rejct)=>{});
let promise1=new Promise((resolve,rejct)=>{});
let promise1=new Promise((resolve,rejct)=>{});
// sange Promise执行完再返回一个新的Promise对象
let p4=Promise.all([promise1,promise2.promise3])
p4.then((resolve)=>{
// 三个都成功才成功
}).catch(err=>{
// 如果一个失败则都失败
})
应用:一些游戏类的素材比较多,等待图片、flash、静态资源文件都加载完成才进行页面的初始化
race方法
race()
给某个异步请求设置超时时间,并且在超时过后执行相应的操作。
race
方法可以用它来做一个请求超时的状态,比如请求一张图片,三秒之后还没请求下来,那么应该告诉用户请求超时了。
function requestImg(imgSrc){
// 返回一个Promise对象
return new Promise((resolve,reject)=>{
// 创建一个img对象
const img=new Image();
// img方法去调用onlode方法去加载,加载的时候执行了一个函数
img.onload=function (){
// 加载成功就直接resolve把img对象返回出去
resolve(img)
}
// 然后给img对象设置src
img.src=imgSrc;
})
}
// 然后有一个延迟的函数,对请求图片设置一个计时
function timeout(){
// 在这里面也是return一个箭头函数
return new Promise ((resolve,reject)=>{
// 设置延迟请求
setTimeout(()=>{
// 3秒还没请求下来就返回失败的信息
reject(new Error("图片请求失败"))
},3000)
})
}
// 接下来通过race方法进行操作
// race方法里面首先接收一个数组里面是图片的路径,第二个参数是timeout方法
// 成功就走requestImg返回图片,请求失败就走timeout返回catch失败
Promise.race([requestImg("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599342328136&di=ea914651a520306f7ce70774b28aa6cb&imgtype=0&src=http%3A%2F%2Fd.hiphotos.baidu.com%2Fzhidao%2Fpic%2Fitem%2Fe61190ef76c6a7efd517f640fbfaaf51f3de66a6.jpg"),timeout()]).then((data)=>{
// 3秒请求成功就走这个代码
console.log(data);
document.body.appendChild(data)
}).catch((err)=>{
// 3秒失败则走这里
})
async()的用法
async方法
的作用:使得异步操作更加方便。
async
是Generator
的一个语法糖。
// async function f(){}这表示当前函数有async异步操作行为
// 基本操作,只要加了async就会返回一个Promise对象,有了这个对象我们就可以通过.then、.catch这些方法来对它进行调用
async function f(){
// 通过await等待。
// 模拟请求一个字符串
let a= await "hello world";
// a请求完过后,拿着a请求回来的结果再次做出请求操作
// split分割字符串
let data= await a.split('');
// 请求结束返回出data
return data;
}
// 因为它返回一个Promise,所以就可以通过.then返回对应的结果
f().then((v)=>{
console.log(v)
})
await
不能单独使用,它一定是在async
语法中。如果async
函数中有多个await
,那么then
函数会等待所有的await
指令运行完,才会去执行
注意:Generator()、 Promise()、 async() 这三个的出现是解决回到地狱问题,使得异步操作更加简洁方便
class类的用法
ES5中造类
function Person(name,age){
this.name=name;
this.age=age;
}
// 创建共有的方法
Person.prototype.sayName=function(){
// 把名字返回出来
return this.name
}
// 实例化对象
let p=new Person("小太阳",18);
console.log(p)
ES6中class语法
class Person{
// constructor:表示在Person函数中添加一个constructor实例方法
// constructor在Person实例化的时候立即调用
constructor(name,age) { //constructor是class原型上的一个方法
this.name=name;
this.age=age;
}
// 给实例赋值一些共享的方法
// 挂载第一个方法
sayName(){
return this.name
} //方法之间不加逗号
// 挂载第二个方法
sayAge(){
return this.age
}
}
let p = new Person("小太阳",17)
console.log(p)
console.log(p.sayName())
console.log(p.sayAge())
通过Object.assign一次性向实例添加多个方法
class Person {
// constructor:表示在Person函数中添加一个constructor实例方法
// constructor在Person实例化的时候立即调用
constructor(name, age) { //constructor是class原型上的一个方法
this.name = name;
this.age = age;
}
}
// 给实例赋值一些共享的方法
// 通过Object.assign一次性向实例添加多个方法
Object.assign(Person.prototype, {
sayName() {
return this.name
},
sayAge() {
return this.age
}
})
let p = new Person("小太阳", 17)
console.log(p)
console.log(p.sayName())
console.log(p.sayAge())
类的继承
在ES6中要想造类的继承就要使用关键字 extends
// 创建一个父类
class Animal{
constructor(name,age) {
this.name=name;
this.age=age;
}
sayName(){
return this.name
}
sayAge(){
return this.age
}
}
// 创建一个子类,希望Dog继承Animal
class Dog extends Animal{
constructor(name,age,color) {
// 希望name和age继承父类
super(name,age) //super表示超类的意思它会去调用他父类中的constructor方法
this.color=color;
}
// 也可以创建子类自己的方法
sayColor(){
return `它叫:${this.name},今年${this.age}岁了,它是${this.color}的`
}
// 重写父类的方法
sayName(){
return this.name+","+this.sayAge()+","+this.color
}
}
let dog=new Dog("小太阳",3,"橙色")
console.log(dog)
console.log(dog.sayColor())
// 继承父类的方法
console.log(dog.sayName())
ES6的模块
一个模块就是一个独立的文件。
ES6模块功能主要有两个命令构成,export
抛出和import
导入
export---抛出
用于模块对外的接口,就是在当前的JS文件中通过export
接口把文件抛出去,然后在另一个脚本文件中通过import
引入
export const name="小太阳";
export const age=18;
export function sayName(){
return "我是小太阳"
}
import---导入
import
用于输入其他模块提供的功能,要引入export
抛出的文件那么就要在<script>
标签中设置type=module
。
import {name,age,sayName} from "./js/index.js";
console.log(name,age,sayName())