一、ES6
1.块级作用域-let和var
- var的设计可以看成JavaScript语言设计上的错误,但这样的错误多半不能修复和移除,因为需要向后兼容
- 可以将let看成更完美的var
- 块级作用域
- JS中使用var来声明一个变量时,变量的作用域主要与函数的定义有关
- 针对其他块定义来说是没有作用域的,比如if/for等,这在开发中会引起一些问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>块级作用域</title>
</head>
<body>
<button>按钮0</button>
<button>按钮1</button>
<button>按钮2</button>
<script>
//ES5语法,没有块级作用域,只有函数的作用域,无论点击哪个按钮都是按钮2,因为i改变了,类似于全局变量
// var btns = document.getElementsByTagName("button");
// for(var i = 0;i<btns.length;i++){
// btns[i].addEventListener("click", function () {
// console.log("第" + i + "个按钮被点击了")
// })
// }
//闭包,利用了ES5的函数作用域来解决没有块级作用域的问题
// var btns = document.getElementsByTagName("button");
// for(var i = 0;i<btns.length;i++){
// (function(i){
// btns[i].addEventListener("click", function () {
// console.log("第" + i + "个按钮被点击了")
// })
// })(i)
// }
//ES6语法,使用let代替var,let有块级作用域
let btns = document.getElementsByTagName("button");
for(let i = 0;i<btns.length;i++){
btns[i].addEventListener("click", function () {
console.log("第" + i + "个按钮被点击了")
})
}
</script>
</body>
</html>
- 程序分析
ES5语法:var定义变量
ES5语法:var定义变量,采用闭包来解决
ES6语法,采用let来定义变量
2.const
- const关键字
- 在很多语言中已存在,主要的作用是将某个变量修饰为常量
- 在JavaScript中使用const修饰的标识符为常量,不可以再次赋值
- 当修饰的标识符不会被再次赋值时,就可以使用const来保证数据的安全性
- 建议:在ES6开发中,优先使用const,只有需要改变某一标识符的时候才使用let
- const的注意:
- 注意一:被const修饰的变量可以看作一个常量,一旦定义了就不能修改,类似于final
- 注意二:const修饰变量时一定要赋初始值
- 注意三:const修饰的对象不能改变,但是对象内部的属性可以修改
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>const</title>
</head>
<body>
</body>
<script>
//1.被const修饰的变量可以看作一个常量,一旦定义了就不能修改,类似于final
// const name = 'hahha';
// name = 'kkk'
//2.const修饰变量时一定要赋初始值
//const name ;
//3.const修饰的对象不能改变,但是对象内部的属性可以修改
const object = {
name : 'hh',
age: 12,
height: 188
}
object.name = 'jj'
object.age = 10
object.height = 185
</script>
</html>
3.变量解构赋值
- ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,这称为解构赋值
- 数组的解构
<script>
const name = ['张三','李四','王五','秦六']
let [zhang,li,wang,qin] = name
console.log(zhang);
console.log(li);
console.log(wang);
console.log(qin);
</script>
- 对象的解构
<script>
//对象的解构
const zhang = {
name:'张三',
age:18,
call:function () {
console.log("我叫张三");
}
}
let {name,age,call} = zhang
console.log(name);
console.log(age);
call()
</script>
4.模板字符串
- ES6引入了新的声明字符串的方式,ES5是采用双引号(" "),单引号(’’),来声明字符串的,但这样有一个弊端,就是不能换行,如果我声明的是一串HTML代码,那么不换行的话,很难阅读,而采取换行需要使用字符串拼接,ES6引入了反引号(``)这个完美解决了换行的问题
<script>
//声明
let string = `字符串`
console.log(string,typeof string);
//内容可以直接换行
let str = `<ul>
<li>zhangsan</li>
<li>lisi</li>
<li>wangwu</li>
</ul>`
//变量拼接
let name = '张三'
let out = `${name}是法外狂徒`
console.log(out);
</script>
5.对象字面变量的增强写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>增强写法</title>
</head>
<body>
</body>
<script>
const name = 'jj'
const age = 15
const height = 188
// ES5写法
// const obj = {
// name: name,
// age: age,
// height: height
// }
// ES6写法
const obj = {
name,
age,
height
}
console.log(obj)
//函数的增强写法
//ES5
const object = {
run:function () {
}
}
//ES6增强写法
const object = {
run() {
}
}
</script>
</html>
6.箭头函数的使用和this指向
(1)基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>箭头函数的基本使用</title>
</head>
<body>
<script>
//箭头函数:也是一直定义函数的方式
//1.定义函数的方式:function
const aaa = function () {
}
//2.对象字面量中定义函数
const obj = {
aaa(){
}
}
//3.ES6中的箭头函数
// const aaa = (参数列表) => {
//
// }
//无参数时
const ccc = () => {
}
</script>
</body>
</html>
(2)参数和返回值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>箭头函数参数和返回值</title>
</head>
<body>
<script>
//1.参数问题
//两个参数
const sum = (num1,num2) => {
return num1 + num2
}
//一个参数(可以把括号省略)
const power = num => {
return num * num
}
//2.返回值
//函数代码块中有多行代码
const test = () => {
console.log('hello world');
console.log('hello vue');
}
//函数代码块中只有一行代码
const mul = (num1,num2) => num1 * num2//自动返回结果
//没有返回值,打印demo的结果时为undefined,调用demo时打印hello world
const demo = () => console.log('hello world');
</script>
</body>
</html>
(3)this的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>箭头函数中this的使用</title>
</head>
<body>
<script>
//什么时候使用箭头函数,一般是作为其他函数的参数时使用
setTimeout(function () {
console.log(this) //这时打印的是window
},1000)
setTimeout(() => {
console.log(this) //这时打印的是window
},1000)
//问题:箭头函数的this是如何查找的?
//答案:向外层作用域中,一层一层查早this,直到有this的定义
const obj = {
aaa(){
setTimeout(function () {
console.log(this) //这时打印的是window
setTimeout(function () {
console.log(this) //这时打印的是window
},1000)
setTimeout(() => {
console.log(this) //这时打印的是window,查找到最外层的setTimeout时发现有this的定义,指向的是window
},1000)
},1000)
setTimeout(() => {
console.log(this) //这时打印的是Obj对象,查找到aaa时发现有this的定义
},1000)
}
}
</script>
</body>
</html>
7.函数参数的默认值设置
- ES6允许给函数的参数赋初始值
<script>
//形参(一般具有默认值的参数要放在后面)
function add(a,b,c = 10) {
return a + b + c
}
console.log(add(1, 2));
console.log(add(1, 2, 3));
//与解构赋值结合
function connect({host = '127.0.0.1',user,password,port}) {
console.log(host);
console.log(user);
console.log(password);
console.log(port);
}
connect ({
host : 'localhost',
user:'root',
password:'root',
port:'3306'
})
</script>
8.rest参数
- ES6引入rest参数,用于获取函数的实参,用来代替argument
<script>
//ES5获取实参的方式
function name() {
console.log(arguments);
}
name('张三','李四','王五')
//ES6rest参数
function name1(...args) {
console.log(args);
}
name1('张三','李四','王五')
//rest参数必须放到最后
function fn(a,b,...args) {
console.log(a);
console.log(b);
console.log(args);
}
fn(1,2,3,4,5)
</script>
9.扩展运算符
- … 扩展运算符能将数组转换为逗号分隔的参数序列
<script>
const name = ['张三','李四','王五']
function kuangtu() {
console.log(arguments);
}
kuangtu(name)
kuangtu(...name)//这样相当于kuangtu('张三','李四','王五')
</script>
- 扩展运算符的应用
<script>
//数组的合并
const name = ['张三','李四']
const name1 = ['王五','秦六']
const kuangtu = name.concat(name1)
const kuangtu1 = [...name,...name1]
console.log(kuangtu);
console.log(kuangtu1);
//数组的克隆
const letter = ['a','b','c']
const colonletter = [...letter]
console.log(colonletter);
//将伪数组转换为真正的数组
const divs = document.querySelectorAll('div')
console.log(divs);
const divArrs = [...divs]
console.log(divArrs);
</script>
10.symbol
(1)Symbol介绍与创建
- ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,是一种类似于字符串的数据类型。
- Symbol特点
- Symbol 的值是唯一的,用来解决命名冲突的问题
- Symbol值不能与其他数据进行运算
- Symbol定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
<script>
//创建一个symbol
let s = Symbol()
console.log(s);
let s1 = Symbol("张三")
let s2 = Symbol("张三")
//s1与s2并不一样
console.log(s1 === s2);
//Symbol.for创建
let s3 = Symbol.for("张三")
let s4 = Symbol.for("张三")
//s3与s4一样
console.log(s3 === s4);
//不能与其他数据运算
// let result = s + 10
// let result = s > 10
// let result = s + "10"
</script>
(2)对象添加Symbol类型属性和方法
- 在不知道对象中是否存在同名的方法,而又不想去改变原对象的同名方法,可以使用Symbol安全地给对象添加相应的方法
<script>
let game = {
name:'游戏',
up(){
console.log('上升');
},
down(){
console.log('下降');
}
}
let methods = {
up:Symbol(),
down:Symbol()
}
game[methods.up] = function() {
console.log('我可以上升');
}
game[methods.down] = function () {
console.log('我可以下降');
}
console.log(game)
let game1 = {
name:'游戏',
[Symbol("up")] : function() {
console.log('上升');
},
[Symbol("down")] : function () {
console.log('下降');
}
}
console.log(game1);
</script>
(3)Symbol的内置属性
- 除了定义自己使用的Symbol值以外,ES6还提供了11个内置的Symbol值,指向语言内部使用的方法。
Symbol.hasInstance | 当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法 |
---|---|
Symbol.isConcatSpreadable | 对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开。 |
Symbol.unscopables | 该对象指定了使用with关键字时,哪些属性会被with环境排除。 |
Symbol.match | 当执行str.match(myObject)时,如果该属性存在,会调用它,返回该方法的返回值。 |
Symbol.replace | 当该对象被str.replace(myObject)方法调用时,会返回该方法的返回值。 |
Symbol.search | 当该对象被str. search (myObject)方法调用时,会返回该方法的返回值。 |
Symbol.split | 当该对象被str. split (myObject)方法调用时,会返回该方法的返回值。 |
Symbol.iterator | 对象进行 for…of循环时,会调用Symbol.iterator 方法,返回该对象的默认遍历器 |
Symbol.toPrimitive | 该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。 |
Symbol. toStringTag | 在该对象上面调用toString方法时,返回该方法的返回值 |
Symbol.species | 创建衍生对象时,会使用该属性 |
11.迭代器
(1)迭代器介绍
- 迭代器(terator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署lterator接口,就可以完成遍历操作。
- ES6 创造了一种新的遍历命令 for…of循环,lterator接口主要供 for…of 消费
- 原生具备iterator接口的数据(可用for…of遍历)
- Array
Arguments
Set
Map
string
TypedArray
NodeList
- Array
- 原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
- 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
- 每调用next方法返回一个包含value 和l done 属性的对象
- 注:需要自定义遍历数据的时候,要想到迭代器。
<script>
const name = ['张三','李四','王五','秦六']
for(let i of name){
console.log(i)
}
for ( let i in name){
console.log(i);
}
let iterator = name[Symbol.iterator]()
console.log(iterator);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
</script>
(2)迭代器自定义数据遍历
<script>
//遍历自定义数据
const Class = {
name : '法外狂徒',
members : [
"zhangsan",
"lisi",
"wangwu",
"qinliu"
],
[Symbol.iterator](){
let index = 0
let _this = this
return{
next:function () {
if(index < _this.members.length) {
const result = {value:_this.members[index],done:false}
index++
return result
}
else {
return {value: undefined,done: true}
}
}
}
}
}
for(let i of Class){
console.log(i);
}
</script>
12.生成器
(1)生成器函数声明与调用
- 生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同
<script>
//生成器函数声明
function * a() {
console.log('111');
}
let iterator = a()
iterator.next()
//嵌套yield,yield可以看作函数代码的分隔符
function * b() {
console.log("第一")
yield '111';
console.log("第二")
yield '222';
console.log("第三")
yield '333';
}
let iterator1 = b()
iterator1.next()
iterator1.next()
iterator1.next()
for(let i of b()){
console.log(i);
}
</script>
(2)生成器函数的参数传递
<script>
function * a(arg) {
console.log(arg);
let one = yield '111'
console.log(one);
let two = yield '222'
console.log(two);
let three = yield '333'
console.log(three);
}
let iterator = a("AAA")
console.log(iterator.next());
console.log(iterator.next("BBB"));
console.log(iterator.next("CCC"));
console.log(iterator.next("DDD"));
</script>
(3)生成器函数实例(解决异步编程,回调地狱的问题)
<script>
//实例
//1s后输出111,2s后输出222,3s后输出333
function one() {
setTimeout(()=>{
console.log('111');
iterator.next()
},1000)
}
function two() {
setTimeout(()=>{
console.log('222');
iterator.next()
},2000)
}
function three() {
setTimeout(()=>{
console.log('333');
iterator.next()
},3000)
}
function * gen() {
yield one()
yield two()
yield three()
}
let iterator = gen()
iterator.next()
</script>
13.Promise
(1)Promise的介绍和基本使用
1)什么是Promise
- ES6中一个非常重要和好用的特性就是Promise
- Promise到底是做什么的呢?
- Promise是异步编程的一种解决方案。
- 那什么时候会来处理异步事件呢?
- 一种很常见的场景应该就是网络请求了。
- 封装一个网络请求的函数,因为不能立即拿到结果,所以不能像简单的3+4=7一样将结果返回。
- 所以往往会传入另外一个函数,在数据请求成功时,将数据通过传入的函数回调出去。
- 如果只是一个简单的网络请求,那么这种方案不会给我们带来很大的麻烦。
- 但是,当网络请求非常复杂时,就会出现回调地狱。
2)网络请求的回调地狱
- 考虑下面的场景(有夸张的成分):
- 通过一个url1从服务器加载一个数据data1 , data1中包含了下一个请求的url2
- 通过data1取出url2,从服务器加载数据data2,data2中包含了下一个请求的url3
- 通过data2取出url3,从服务器加载数据data3 ,data3中包含了下一个请求的url4
- 发送网络请求url4,获取最终的数据data4
$.ajax( 'url1', function (data1) {
$.ajax(data1 ['url2 '], function (data2){
$.ajax(data2 ['url3'],function (data3){
$.ajax(data3 ['url4'],function (data4){
console.log(data4);
})
})
})
})
- 上面的代码有什么问题吗?
- 正常情况下,不会有什么问题,可以正常运行并且获取想要的结果。
- 但是,这样的代码难看而且不容易维护。
- 我们更加期望的是一种更加优雅的方式来进行这种异步操作。
- 如何做呢?就是使用Promise。
- Promise可以以一种非常优雅的方式来解决这个问题。
3)定时器的异步事件
- 用一个定时器来模拟异步事件:
- 假设下面的data是从网络上1秒后请求的数据
- console.log就是我们的处理方式。
setTimeout(()=>{
let data1 = 'Hello World'
console.log(data1);
setTimeout(() =>{
let data2 = 'Hello Vuejs'
console.log(data2);
},1000)
},1000
- 这是过去的处理方式,将它换成Promise代码
//resolve,reject作为Promise的参数
//resolve,reject本身也是函数
new Promise((resolve ,reject)=>{
//第一次网络请求
setTimeout(()=>{
resolve('Hello World')
reject('error')
},1000)
}).then( data =>{
//第一次处理
console.log(data);
//第二次网络请求
return new Promise((resolve ,reject)=>{
setTimeout(()=>{
resolve('Hello Vuejs')
},1000)
}).then( data =>{
//第二次处理
console.log(data);
})
}).catch( error =>{
//错误处理
console.log(error);
})
(2)Promise的三种状态
- 首先,当开发中有异步操作时,就可以给异步操作包装一个Promise
- 异步操作之后会有三种状态:
- pending :等待状态,比如正在进行网络请求,或者定时器没有到时间。
- fulfill :满足状态,当主动回调了resolve时,就处于该状态,并且会回调.then()
- reject:拒绝状态,当主动回调了reject时,就处于该状态,并且会回调.catch()
- Promise的另外一种写法:
- catch中的内容可以写在then中
new Promise((resolve ,reject)=>{
//第一次网络请求
setTimeout(()=>{
resolve('Hello World')
reject('error')
},1000)
}).then( data =>{
//第一次处理
console.log(data);
//第二次网络请求
return new Promise((resolve ,reject)=>{
setTimeout(()=>{
resolve('Hello Vuejs')
},1000)
}).then( data => {
//第二次处理
console.log(data);
})
},error =>{
//错误处理
console.log(error);
})
(3)Promise的链式调用
- 无论是then还是catch都可以返回一个Promise对象。
- 所以,代码其实是可以进行链式调用的:
- 这里直接通过Promise包装了一下新的数据,将Promise对象返回了
- Promise.resovle():将数据包装成Promise对象,并且在内部回调resolve()函数
- Promise.reject():将数据包装成Promise对象,并且在内部回调reject()函数
// 链式调用的代码
new Promise( (resolve,reject) =>{
setTimeout( function() {
resolve( 'Hello World ' )
},1000)
}).then(data => {
console.log(data);//=>Hello World
return new Promise(resolve => {
resolve(data + '111')
})
}).then( data => {
console.log(data);// => Hello World111
return new Promise(resolve => {
resolve(data + '222')
})
}).then(data => {
console.log(data);//=>Hello World111222
return new Promise((resolve,reject) => {
reject(data + 'error')
})
}).then(data => {
console.log(data);// 这里没有输出,这部分代码不会执行
return new Promise(resolve => {
resolve(data + '333')
})
}).catch(data => {
console.log(data);// =→>Hello world111222error
return new Promise(resolve => {
resolve(data + '444')
})
}).then(data => {
console.log(data);//=> Hello World111222error444
})
- 简写一
//简写一
new Promise( (resolve,reject) =>{
setTimeout( function() {
resolve( 'Hello World ' )
},1000)
}).then(data => {
console.log(data);//=>Hello World
return Promise.resolve(data + '111')
}).then(data => {
console.log(data);// => Hello World111
return Promise.resolve(data + '222 ')
}).then(data => {
console.log(data);//=>Hello World111222
return Promise.reject(data + 'error ')
}).then(data => {
console.log(data);// 这里没有输出,这部分代码不会执行
return Promise.resolve(data + '333 ')
}).catch(data => {
console.log(data);// =→>Hello world111222error
return Promise.resolve(data + '444')
}).then(data => {
console.log(data);//=> Hello World111222error444
})
- 简写二
//简写二
new Promise( (resolve,reject) =>{
setTimeout( function() {
resolve( 'Hello World ' )
},1000)
}).then(data => {
console.log(data);//=>Hello World
return data + '111'
}).then(data => {
console.log(data);// => Hello World111
return data + '222 '
}).then(data => {
console.log(data);//=>Hello World111222
throw data + 'error'
}).then(data => {
console.log(data);// 这里没有输出,这部分代码不会执行
return data + '333'
}).catch(data => {
console.log(data);// =→>Hello world111222error
return data + '444'
}).then(data => {
console.log(data);//=> Hello World111222error444
})
(4)Promise的all方法的使用
- all方法可以等待在其内部的所有请求都返回结果后全部获取出来
Promise.all([
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve({name:'zhangsan',age:18})
},2000)
}),
new Promise((resolve,reject)=>{
resolve({name:'lisi',age:19})
},1000)
]).then( result =>{
console.log(result);
})
- 运行截图
14.集合Set
(1)集合介绍
- ES6提供了新的数据结构Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用扩展运算和for…of进行遍历,集合的属性和方法:
- size返回集合的元素个数
- add增加一个新元素,返回当前集合
- delete删除元素,返回boolean值
- has检测集合中是否包含某个元素,返回boolean值
- clear清空集合,返回undefined
<script>
//声明一个集合
let s = new Set
let s1 = new Set(['111','222','333'])
console.log(s1.size);
s1.add('444')
console.log(s1);
s1.delete('444')
console.log(s1);
console.log(s1.has('111'));
for (let i of s1){
console.log(i);
}
s1.clear()
console.log(s1);
</script>
(2)集合实践
<script>
const arr = [1,1,2,3,3,4,5,5,6]
//去重
let one = [...new Set(arr)]
console.log(one);
//交集
const arr2 = [4,5,6,7,8]
let two = [...new Set(arr)].filter(item =>{
let s2 = new Set(arr2)
if(s2.has(item)){
return true
}else
return false
})
console.log(two);
//并集
let three = [...new Set([...arr,...arr2])]
console.log(three);
//差集
let four = [...new Set(arr)].filter(item =>{
let s2 = new Set(arr2)
if(!s2.has(item)){
return true
}else
return false
})
console.log(four);
</script>
15.Map
- ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,所以可以使用扩展运算符和for…of进行遍历。Map的属性和方法:
- size返回Map的元素个数
- set增加一个新元素,返回当前Map
- get返回键名对象的键值
- has检测 Map中是否包含某个元素,返回 boolean值
- clear清空Map,返回undefined
<script>
let m = new Map
m.set('name','zhangsan')
m.set('eat',function () {
console.log('吃饭')
})
let key = {
province : '省份'
}
m.set(key,["北京","天津","河北"])
comsole.log(m);
console.log(m.size);
console.log(m.get('name'));
console.log(m.get(key));
m.delete('name')
console.log(m);
// m.clear()
// console.log(m);
</script>
16.Class
(1)Class介绍
- ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6 的 class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
- 知识点:
- class声明类
- constructor定义构造函数初始化
- extends 继承父类
- super调用父级构造方法
- static定义静态方法和属性
- 父类方法可以重写
<script>
//ES5
function Phone(brand,price) {
this.brand = brand
this.price = price
}
//添加方法
Phone.prototype.call = function () {
console.log('打电话');
}
//实例化对象
let Huawei = new Phone("华为",4999)
Huawei.call()
console.log(Huawei);
//ES6
class TelPhone{
//构造方法
constructor(brand,price) {
this.brand = brand
this.price = price
}
call(){
console.log('打电话');
}
}
let onePlus = new TelPhone("一加",3999)
onePlus.call()
console.log(onePlus);
</script>
(2)静态成员
- 静态成员的意思是,变量或者函数是属于这个类的,而不属于实例对象,所以实例对象并不能使用它们
<script>
//ES5
function Phone() {
}
Phone.name = '手机'
Phone.call = function () {
console.log('打电话');
}
Phone.prototype.size = 5.5
let huawei = new Phone()
console.log(huawei.name);
console.log(huawei.size);
//ES6
class TelPhone{
static name = '手机'
static call(){
console.log('打电话');
}
}
let nokia = new TelPhone()
console.log(nokia.name);
</script>
(3)类继承
<script>
class phone{
constructor(brand,price) {
this.brand = brand
this.price = price
}
}
class smartPhone extends phone{
constructor(brand,price,color,size) {
super(brand,price);
this.color = color;
this.size = size;
}
playGame(){
console.log('玩游戏');
}
}
let xiaomi = new smartPhone('小米',2000,'黑色',5.5)
console.log(xiaomi);
xiaomi.playGame()
</script>
(4)子类对父类方法的重写
<script>
class phone{
constructor(brand,price) {
this.brand = brand
this.price = price
}
call(){
console.log('打电话');
}
}
class smartPhone extends phone{
constructor(brand,price,color,size) {
super(brand,price);
this.color = color;
this.size = size;
}
playGame(){
console.log('玩游戏');
}
call(){
console.log('视频通话');
}
}
let xiaomi = new smartPhone('小米',2000,'黑色',5.5)
console.log(xiaomi);
xiaomi.playGame()
xiaomi.call()
</script>
(5)get和set
<script>
class phone{
get Price(){
console.log('属性被读取了');
return '1000元'
}
set Price(newValue){
console.log('属性被修改了');
}
}
let s = new phone()
console.log(s.Price);
s.Price = 'free'
</script>
17.数值扩展
<script>
//Number.EPSILON是JavaScript表示的最小精度
console.log(0.1 + 0.2 === 0.3);//这样实际是不相等的
function equal(a,b) {
if(Math.abs(a-b) < Number.EPSILON){
return true
}else {
return false
}
}
//如果两者相减,精度小于Number.EPSILON,可以认为两者相等
console.log(equal(0.1 + 0.2, 0.3));
//进制
//二进制
let b = 0b1010
//八进制
let o = 0o777
//十六进制
let h = 0x100
console.log(b);
console.log(o);
console.log(h);
//Number.isFinite()检测一个数值是否为有限数,是返回true,不是返回false
console.log(Number.isFinite(100));
console.log(Number.isFinite(100 / 0));
//Number.isNaN()检测一个数值是否为NaN,是返回true,不是返回false
console.log(Number.isNaN(100));
//Number.parseInt() Number.parseFloat(),字符串转整数,浮点数
console.log(Number.parseInt('123aaa'));
console.log(Number.parseFloat("1.23aaa"));
//Number.isInteger() 判断一个数是否为整数,是返回true,不是返回false
console.log(Number.isInteger(100.1));
//Math.trunc(),将小数部分抹掉
console.log(Math.trunc(1.1));
//Math.sign(),判断一个数是否为正数,负数,或零,正数返回1,负数返回-1,零返回0
console.log(Math.sign(-100));
console.log(Math.sign(0));
console.log(Math.sign(100));
</script>
18.对象方法扩展
<script>
// Object.is() 判断两个值是否完全相等,类似于===
console.log(Object.is(120, 120));
console.log(Object.is(NaN, NaN));//这样是相等的
console.log(NaN === NaN);//这样是不等的
//Object.assign(),对象的合并
const info = {
name : 'zhangsan',
age: 18
}
const info1 = {
age:20,
height:180
}
//若对象存在同名属性,后面的对象属性会将前面的对象属性覆盖
console.log(Object.assign(info, info1));
//Object.setPrototypeOf() 设置原型对象 Object.getPrototypeOf() 获取原型对象
const province = {
province: "省份"
}
const cites = {
cites : ['北京','上海','南京']
}
Object.setPrototypeOf(province,cites)
console.log(Object.getPrototypeOf(province));
console.log(province);
</script>
19.ES6模块化的导入和导出
export基本使用
- export指令用于导出变量,例如:
// info.js
export let name = '张三'
export let age = 18
export let height = 1.88
- 另一种写法
// info.js
let name = '张三'
let age = 18
let height = 1.88
export (name,age,height)
- export导出函数或类
export function test(content) {
console.log(content);
}
export class Person {
constructor(name,age) {
this.name = name ;
this.age = age;
}
run(){
console.log(this.name + "在奔跑");
}
}
- 另一种写法
function test(content){
console.log(content);
}
class Person {
constructor(name, age){
this.name = name ;
this.age = age ;
}
run() {
console.1og(this.name +"在奔跑");
}
}
export {test,Person}
- export default
- 某些情况下,一个模块中包含某个的功能,我们并不希望给这个功能命名,而且让导入者可以自己来命名,这个时候就可以使用export default
// info.js
export default function o {
console.1og ( 'default function ' );
}
- 我们来到main.js中,这样使用就可以了
这里的myFunc是自己命名的,你可以根据需要命名它对应的名字
//mian.js
import myFunc from './info.js '
myFunc()
- 另外,需要注意: export default在同一个模块中,不允许同时存在多个。
import的基本使用
- 使用export指令导出了模块对外提供的接口,可以通过import命令来加载对应的这个模块了
- 首先,我们需要在HTML代码中引入两个js文件,并且类型需要设置为module
<script src="info.js" type="module"></script>
<script src="main.js" type="module"></script>
- import指令用于导入模块中的内容,比如main.js的代码
import {name,age,height} from "./info.js"
console.log(name, age,height);
- 如果希望某个模块中所有的信息都导入,一个个导入显然有些麻烦;
- 通过*可以导入模块中所有的export变量
- 但是通常情况下我们需要给*起一个别名,方便后续的使用
import * as info from './info.js'
console.log(info.name,info.age, info.height,info.friends);