概念
javascript 是什么?
一门弱类型的脚本语言(高级编程语言)。简称JS
弱类型?
声明变量存储数据的语法比较自由,不是很严谨。
任何类型的数据(string/number/boolean/undefined/null...),都可以通过var关键字声明变量进行存储。
javascript
var a = "hello"
var b = 123;
var c = true;
强类型?例如java
int a ; boolean c;
ES6是什么
ECMAScript 6(简称ES6)是于2015年6月正式发布的JavaScript语言的标准,
正式名为 ECMAScript 2015(ES2015)。
简单点:ES6 就是javascript的第六个版本。(在2015之后发布的新增内容都在这个ES6)
为什么使用ES6?
ES6大部分浏览器都支持(ES5语法是所有浏览器都支持的)。 Babel 插件把ES6代码编译ES5代码
ES6的出现是为了弥补ES5的先天不足(变量、常量)。
目前市场上大多数的技术框架都是结合ES6语法或者typescript语法进行开发。(市场有需求)
ES6语法比较简约(箭头函数)、新增了许多实用的功能(数组API)。引入类的概念(面向对象的写法统一了)
//ES5 中不会报错 (变量重复声明,值可以随意修改)
var a = "hello";
a = 123;
var a = true;
VS
// ES6 语法比ES5要更加严谨、更加合理
const a = "hello";
a = 123; // 报错
const a = true; // 错误
互联网编程语言的排行榜...
有哪些新特性
声明变量 (let)
ES5 使用var关键字 (比较自由)
ES6 使用let关键字 (比较严谨、合理)
有什么优点:
1、不允许变量声明提升(必须先声明后使用)
2、不允许重复声明变量
3、可以产生块级作用域 { 局部代码可执行环境 }
变量是什么?有什么作用?
变量是存储数据的容器(给数据起个名字)。主要用于存储数据、记录数据。
var a = 100;
实际上就是在内存中开辟小块空间名称叫做a, 用于存储数据100。
// ES5
// 变量声明可以提升(名称提升了,但是值没有提升)
// console.log(a);// undefined
// var a = 100;
// console.log(a);// 100
// 1) Uncaught ReferenceError: aaa is not defined
// console.log(aaa);// 内存中没有aaa这个变量,所有浏览器不能识别aaa,所以报错
// ES6
// 1) let 声明的变量,没有提升这个说法(必须先声明后引用,否则报引用类型错误)
// console.log(b);
let b = 100;
// console.log(b);// 100
// 2) 不允许变量重复声明,否则报错
// Uncaught SyntaxError: Identifier 报语法类型错误
// let b = 'hello';
// 3) 块级作用域 可以直接使用 { } 块级作用域;也可以是if语句、for语句、函数的大括号{}
// var index = 0;
// var index = 1;
// var index = 2;
// console.log(index);// 2
// for(var i = 0 ; i <= 10 ; i ++){
// }
// console.log(i);// 控制台输出的变量i是多少?11 ,因为var关键字声明的i是全局的,走出循环i++
// 有了块级作用域,甚至都不需要使用闭包了。
{
let index = 0;
console.log(index);// 0
}
{
let index = 1;
console.log(index);// 1
}
{
let index = 2;
console.log(index);// 2
}
// console.log(index);// 报错,因为全局环境下没有这个变量
for(let j = 0 ; j <= 10 ; j ++) {
// let 会产生块级作用域,只能在 {} 中使用
console.log(j);
}
// console.log(j);// 控制台输出的变量j是多少? 报错
声明常量 (const)
// 变量(值可以改变的)
let a = 100;
a = 99;
a = 98;
// 常量 (值是固定的,不能直接改变的)
const b = 100;
// b = 99;
// 不能直接给常量赋值
// TypeError: Assignment to constant variable.
// 编写函数名称就可以使用常量
const login = function () { }
// 也有let关键字的特点1)不能声明提升 2)不能重复声明3)也有块级作用域
// 区别就是const声明的是常量,不允许重新赋值
const c = true;
// c = false;//报错
// 面试题:
const arr = [100, 200, 300];
// 直接修改
// arr = ['red','green','blue'];// 报错
// 间接修改
arr[0] = 'red';
arr[1] = 'green';
arr[2] = 'blue';
console.log(arr);// 不报错,因为arr仍然是同一个引用地址,改变不过是引用地址里面的数据。
// 遇到数组、对象这些引用类型数据时,可以间接的通过索引值或者键值对修改引用地址里面的数据。
模板字符串
// 填充字符串(反单引号)
// ${变量} 把变量插入到模板中
ul.innerHTML = `
<li>
<p class="message">${text}</p>
</li>
`
解构赋值(数组、对象)
// 存储数据的方式,声明变量
// var a = 100;
// var b = 200;
// var c = 300;
// console.log(a,b,c);// 100 200 300
// 如果这些数据100 200 300 都是在数组中呢?在数组中如何取值
// 1) 可以通过索引值0 1 2进行取值
// var arr = [100,200,300];
// console.log(arr)
// console.log(arr[0]);// 100
// console.log(arr[1]);// 200
// console.log(arr[2]);// 300
// 解构:解剖结构
// 修饰关键字 变量 = 值
// 隐式变量 = 值 (没有关键字 在严格模式下是不允许)
// 解构赋值(比较常用的语法)
// 数组 []
// 索引值0 1 2,....
// 2) 可以通过数组解构赋值
// 等于号左右两侧结构需要一致,可以全部取值,也可以取出部分的值
let [a, b, c] = [100, 200, 300];
// console.log(a);// 100
// console.log(b);// 200
// console.log(c);// 300
let [, , g] = [100, 200, 300];
console.log(g);// 300
let [, , blue] = ['red', 'green', 'blue'];
console.log(blue);// 'blue'
let [[[num]]] = [[[100]]];
console.log(num);// 100
// 对象 {}
// 键值对
let point = { x: 300, y: 400, color: 'red' };
let { x, y, color } = point;
console.log(x);// 300
console.log(y);// 400
console.log(color);// 'red'
// 示例1:
let { code, result } = { code: 200, result: [{ name: '小明' }, { name: '小红' }, { name: '小兰' }] }
console.log(code);// 200
console.log(result);//[{name:'小明'},{name:'小红'},{name:'小兰'}]
// 示例2:
let { result: [item1, item2, item3] } = { code: 200, result: [{ name: '小明' }, { name: '小红' }, { name: '小兰' }] }
console.log(item1);// {name: '小明'}
console.log(item2);// {name: '小红'}
console.log(item3);// {name: '小兰'}
// 示例3:
let { result: [{ name: n1 }, { name: n2 }, { name: n3 }] } = { code: 200, result: [{ name: '小明' }, { name: '小红' }, { name: '小兰' }] }
console.log(n1);// '小明'
console.log(n2);// '小红'
console.log(n3);// '小兰'
// 总结:
// 针对数组、对象提供了一种快捷取值的方法
// 取值的方式有很多种,ES6提供了新的方式。那我们可以学习加以使用
// 等于号左右两侧结构需要一致,可以全部取值,也可以取出部分的值
// let [ 变量1, 变量2, 变量3 ] = 数组
// let { 变量4, 变量5, 变量6 } = 对象
// 变量名称不能冲突了。。。。
对象语法糖(简写)
// 语法糖:某种语法的简写
let color = "red";
let width = "100px";
let height= "100px";
// 定义对象
let obj = {
color,
width,
height
}
console.log(obj);// {color: 'red', width: '100px', height: '100px'}
// 定义变量,这些变量可以作为对象的key
let x = 50;
let y = 100;
let w = 200;
let h = 300;
// 直接输出变量,检查变量是否有值
// console.log({x,y,w,h});
let point = {
x,y,w,h
}
console.log(point);// {x: 50, y: 100, w: 200, h: 300}
// 可以把变量作为对象的key,写在大括号 {变量} 最终会形成 {变量: 值} 。
箭头函数
函数是什么?函数是代码块
是可重复执行的代码块。
是指可以实现特定功能的代码块。
提示:定义函数,需要调用函数,代码块才被执行。。。
普通函数:
function foo(){
}
foo()
构造函数:
function App(){
this.version = "v1.0.0";
}
new App();
箭头函数:
强调一下,箭头函数不能作为构造函数,不能使用new来调用,因为箭头函数作用域没有this这个概念。
使用箭头 “ =>” 来声明的函数叫做箭头函数(也是可重复利用的代码块)
// 示例1: 区别普通函数和箭头函数写法
// 普通函数
// var foo = function(){
// console.log("我是普通函数")
// }
// foo();
// 箭头函数
// const boo = () => {
// console.log("我是箭头函数")
// }
// boo();
// 示例2:返回值
// return 需要在函数作用域中才起作用
const getRadomNum = ()=> {
// 返回0~100之间的随机整数
return Math.floor(Math.random() * 100);
}
// let v1 = getRadomNum();
// console.log({v1});// {v1: 随机数}
const getRadomNum = ()=> 返回值;
// 示例3:传参
// 形参和实参
// 形参就是局部变量
// 实参就是数据
// 有参数并且是一个参数的情况下,可以省略小括号 ()
// const sayHello = (userName)=> {
// console.log(`${userName},你好。`);
// }
// const sayHello = userName => {
// console.log(`${userName},你好。`);
// }
// sayHello("小明");
// sayHello("小新");
// 两个参数以上
const speaking = (userName, message)=> {
console.log(`${userName},${message}`);
}
// speaking("小明", "你看看你,一天天的,就知道吃");
// speaking("xiaoming", "You see see you, one day day , just to eat");
// 参数默认值
// const add = (a,b) => {
// return a + b;
// }
// const v2 = add();
// console.log({v2});// {v2:NaN}
// undefined + undefined = NaN
// const add = (a=1,b=2) => {
// return a + b;
// }
// const v2 = add();
// console.log({v2});// {v2:3}
// 示例4: this 指向
// 情况一:
// const foo = ()=> {
// console.log(this);// 上一级作用域(就是全局作用 this | window)
// }
// foo();
// 情况二:
// document.querySelector(".btn").onclick = function(){
// console.log(this);// 事件调用者 <button class="btn">点击一下</button>
// }
document.querySelector(".btn").onclick = () => {
console.log(this);// // 上一级作用域(就是全局作用 this | window)
}
// 情况三:
// let obj = {
// foo: function(){
// console.log(this);// this 指向 obj 对象
// }
// }
// obj.foo();
// let obj = {
// foo: ()=>{
// console.log(this);// this 指向 window对象
// }
// }
// obj.foo();
// 情况四:
function App(){// 构造函数作用域 this 指向App构造函数的实例
this.version = "V1.0.0";
// 单独定义变量记录实例对象 _this that xxx
var xxx = this;
setTimeout(function(){// 延迟定时器函数作用域 this 指向window对象
console.log('1:',this.version);// 可不可以获取这个字符串 “"V1.0.0"” ? 不可以,是undefined
console.log('2:',xxx.version);// 可不可以获取这个字符串 “"V1.0.0"” ? 可以
},100)
setTimeout(()=>{
console.log('3:',this.version);// 可不可以获取这个字符串 “"V1.0.0"” ? 可以
},100)
}
// new App();
//示例5: 把以下代码改成使用箭头函数
var f1 = function(x){
return function(y){
return function(color){
return {
x,y,color
}
}
}
}
// 单一传递参数的函数(柯里化函数)
var v3 = f1(100)(200)('red');
console.log(v3);// {x: 100, y: 200, color: 'red'}
// 箭头函数 (特殊写法)
const f2 = x => y => color => {
return {x,y,color}
}
或者
const f2 = x => y => color => {x, y, color}
var v4 = f2(100)(200)('blue');
console.log(v4);// {x: 100, y: 200, color: 'red'}
拓展运算符 ...
// 拓展运算符
// ...
// 作用:
// 1. 复制数据集合中的数据
// 2. 展开集合中的数据
// 3. 处理剩余参数
// 定义数组
let arr1 = [100,200,300];
let arr2 = [400,500,600];
// 回想之前的“浅拷贝”
let newArr = [... arr1, ... arr2];
// console.log(newArr);// [100,200,300,400,500,600]
// 展开集合中的数据
// console.log(... arr1);// 100 200 300
// let obj = {x:"100px",y:"200px"};
// console.log(... obj);// 报类型错误
// 处理剩余参数(实参比形参数量要多的情况下)
// 后续在vuex插件中可以使用
//ES6
const foo = (a,b,c, ... rest)=> {
console.log(a);
console.log(b);
console.log(c);
console.log(rest);// [4,5,6,7,8]
// console.log(arguments);// 在箭头函数作用域中 无法使用arguments对象
// 否则报错 Uncaught ReferenceError: arguments is not defined
}
foo(1,2,3,4,5,6,7,8);
字符串&数组新增的API
// 字符串(带有引号的数据都叫字符串 'abc' "abc" `abc`)
// 面试题:请你列举5个字符串操作API?
// slice()
// indexOf()
// replace()
// toUpperCase()
// toLowerCase()
// split()
// ....
let src = "https://www.xxxx.com/static/demo.jpg";
var v1 = src.startsWith('https');// 判断是否以 'https' 开头
var v2 = src.startsWith('file');
var v3 = src.includes('static'); // 判断是否包含 'static'
var v4 = src.endsWith('.jpg');// 判断是否以 '.jpg' 结束
var v5 = src.endsWith('.txt');
console.log({v1,v2,v3,v4,v5});
// console.log({v1,v2,v3,v4,v5});
// 数组(特征:具有length属性以及通过索引去存值或取值的数据集合)
// 伪数组 (具有数组的特征,但是不能调用数组的方法)
// let divs = document.getElementsByTagName("div");
// console.log(divs);
// divs.push("aaa");// 报错
// 定义数组
let arr = ['aaa', 'bbb', 'ccc', 'ddd'];
// 1) 循环
arr.forEach((item, index) => {
// console.log(item);// 代表的是数组的每一项数组 (以后在框架开发中经常这个"item")
// console.log(index);// 索引
})
// 2)映射(一一对应的意思)
// 可以映射出一个新数组
// let newArr = arr.map((item)=>{
// return item.toUpperCase();
// })
// console.log(newArr)
// 定义数组
let students = [
{ name: "小明", socre: 60, id: 1 },
{ name: "小红", socre: 50, id: 2 },
{ name: "小兰", socre: 80, id: 3 },
{ name: "小清", socre: 30, id: 4 },
{ name: "小黄", socre: 90, id: 5 }
]
// 根据数据映射一个新数据,标注哪些同学是及格的(>=60),哪些同学是不及格的(< 60)
// 以后react中有着重要的作用(jsx 做列表渲染)
let newStudents = students.map((item) => {
// 根据分数做判断
if (item.socre >= 60) {
item.text = "及格的"
}
else {
item.text = "不及格的"
}
return item;
})
// console.log(newStudents);
// 3) 过滤
// 过滤掉分数低于60分的同学
let data = students.filter((item)=>{
// 判断分数是否大于等于60
if(item.socre>=60){
// 返回(保留)
return item;
}
})
// console.log(data);
// 4) reduce (累计计算)
let result = [1,2,3,4,5,6] // 全部加起来等于21
let total = result.reduce((prev,next)=>{
return prev + next;
})
console.log("累计计算的结果:",total);// 累计计算的结果: 21
Set和Map
// Set
// 这个函数可以操作数组
// 1. 可以把数组中重复的数据过滤掉(让数组中的数据不重复)
// 2. 提供对数组进行新增、删除等相关功能
// 定义数组
let arr = ['a','b','c','a','b','c','d','e'];
// 编程题:如何实现数组去重?
// let obj = {};
// let newArr = [];
// for(let i = 0 ; i < arr.length ; i ++){
// // 这个key其实就是arr数组的每一项数据
// let key = arr[i];
// if(obj[key] === undefined) {
// // 把首次出现的key添加到新数组中
// newArr.push(key);
// // 给obj对象的key赋值
// obj[key] = 1;
// }
// }
// // 循环结束,数组去重了
// console.log(newArr);// ['a', 'b', 'c', 'd', 'e']
// ES6
// 数组去重
let setObj = new Set(arr);
let newArr2 = [... setObj];
console.log(newArr2);// ['a', 'b', 'c', 'd', 'e']
// 添加数据
setObj.add('f');
setObj.add('g');
// console.log(setObj);// Set(6) {'a', 'b', 'c', 'd', 'e','f','g'}
// 删除数据
setObj.delete('a');
console.log(setObj);// Set(6) {'b', 'c', 'd', 'e','f','g'}
// 判断集合中是否存在这个数据
console.log(setObj.has('c'));// true
console.log(setObj.has('x'));// false
// Map
// 这个函数可以操作对象
// 主要是提供可操作对象的API
let mapObj = new Map();
// 普通对象(键要么是数字,要么是字符串)
let obj = {
0: '100px',
'width':'100px'
}
// 设置键值对 (键可以是任意类型数据)
mapObj.set("width","100px");
mapObj.set("height","100px");
mapObj.set("color","red");
mapObj.set(true,10010);
// 获取键对应的值
let w = mapObj.get("width");
let h = mapObj.get("height");
let c = mapObj.get("color");
console.log({w,h,c});
// 删除对象中指定的数据
mapObj.delete("color");
// 循环mapObj对象
mapObj.forEach((value,key)=>{
console.log(value,'---->',key);
})
console.log(mapObj);//Map(3) {'width' => '100px', 'height' => '100px', true => 10010}
Proxy和Reflect
// Reflect
// 主要是针对对象进行操作
let data = {
message: "好消息"
}
// 观察Reflect对象
// console.log(typeof Reflect);// 'object' 对象
// 观察Reflect对象结构,看这个对象都有哪些方法?
console.dir(Reflect);
// 1) 获取指定对象的属性值
let v1 = Reflect.get(data, 'message');
console.log(v1);// '好消息'
// 2) 设置指定对象的键值对
Reflect.set(data, "name", "小明");
Reflect.set(data, "age", 20);
// 3) 删除指定对象的属性
Reflect.deleteProperty(data, 'age');
// 控制台输出:
console.log(data);//{message: '好消息', name: '小明'}
// 4) 判断指定对象是否存在message这个键
console.log(Reflect.has(data, 'message'));// true
console.log(Reflect.has(data, 'xxx'));// false
// ES5
// console.log(data.message);// '好消息'
// Proxy (Vue3做响应式是基于这个函数)
// 这是构造函数
// console.log(typeof Proxy);// 'function'
// 可以代理对象,在Vue@3.x内部封装就采用了这个函数对数据进行监听,从而实现数据响应式。
// 主要是可以做拦截、数据响应式
let obj = {}
let proxyObj = new Proxy(obj, {
// 监听对象的读写
// 监听对象是否取值了
// get:function(){},
get(target, key) {
// console.log("读取");
// 拦截 对“age”这个属性进行拦截了
if(key=="age") {
return "不告诉你";
}
// 返回属性值
return target[key];
},
// 监听对象是否赋值了
set(target, key, value) {
// console.log("写入")
// 赋值
target[key] = value;
}
})
// 关于对象的取值和赋值
proxyObj.message = "hello world";// 赋值
proxyObj.age = 100;// 赋值
proxyObj.message;// 取值
console.log(proxyObj.age);// "不告诉你"
console.log(proxyObj.message);// "hello world"
// 示例:感受一下什么叫做数据响应式
let inp = document.querySelector("input[type='text']");
let box = document.querySelector("div[class='box']");
let data2 = {
msg:""
};
// 数据修改了,可以改变页面(响应式)
let pObj = new Proxy(data2,{
set(target,key,value){
// 赋值
target[key]=value;
// 修改box标签的文本
box.innerHTML = value;
box.style.backgroundColor = value;
}
})
// 给输入框添加事件
inp.addEventListener('input',function(){
// 获取输入的值
let v1 = inp.value;
// 给pObj.msg属性赋值(通过修改msg,改变box标签的文本)
pObj.msg = v1;
})
Promise 处理异步编程(必须)
// 示例1:
// 开关,布尔值为true,
// 执行第一个then方法的第一个回调函数
// 否则false就执行第一个then方法的第二个回调函数
let isShow = true;
// 创建promise
let p1 = new Promise((resolve,reject)=>{
if(isShow){
resolve("符合条件");
}
else {
reject("不符合条件");
}
})
// console.log(p1);// Promise {} 这是promise实例, 可以实现链式操作
p1
.then(
(msg)=>{
console.log(msg);// '符合条件'
return 111
},
(err)=> {
console.log(err);// '不符合条件'
}
)
.then(
(msg)=>{
console.log(msg);// 111 上一个then方法的第一个回调函数没有返回值,此处就是undefined
return 222;
}
)
.then(
(msg)=>{
console.log(msg);// 222
}
)
// 示例2:
let p2 = new Promise((resolve,reject)=>{
if(false){
resolve();
}
else {
reject();
}
})
p2.
then(
()=>{
console.log("1.0 符合条件")
}
)
.catch(
()=>{
console.log("2.0 不符合条件")
}
)
.finally(
()=>{
console.log("3.0 不管是否符合条件,最后都执行")
}
)
// 总结:
// Promise是一种解决异步编程的方案。
// 创建Promise实例,其实这个Promise实例就是一套处理业务的逻辑(例如:登录的逻辑,加入购物车的逻辑,支付的逻辑)
// 可以通过实例对象链式调用then方法,不断执行“下一个”逻辑,从而代替“回调地狱”
// Promise实例可以调用then方法,catch方法,finally方法。
async 和 await 语法 (必须掌握)
既可以处理同步编程,也可以处理异步编程。
往往需要配合Promise使用,不然await不起作用。(await这个修饰符需在async函数作用域中使用)
const init = async ()=> {
执行业务1
await 登录promise
await 收藏promise
await 收藏列表promise
执行业务2
}
// 示例1: async 关键字 (处理异步)
// const sayHello = async () => {}
const sayHello = async function(){
console.log("首先。。。。")
return 111;
}
// const pro = sayHello();
// console.log(pro);
// pro
// .then(
// (result)=>{
// console.log("然后。。。。1", result);// 然后。。。。1 111
// }
// )
// .then(
// (result)=>{
// console.log("然后。。。。2",result);// 然后。。。。2 undefined
// }
// )
// .then(
// ()=>{
// console.log("然后。。。。3")
// }
// )
// .then(
// ()=>{
// console.log("然后。。。。4")
// }
// )
// 示例2: async 和 await (既可以处理同步,也可以处理异步)
// const speaking = async function(){
// console.log("第一件事情:起床");
// await setTimeout(()=>{ console.log("第二件事情:吃早餐") },300)
// await setTimeout(()=>{ console.log("第三件事情:上课") },300)
// console.log("第四件事情:下课");
// }
// speaking();
// 配合promise使用
const speaking = async function(){
console.log("第一件事情:起床");
await new Promise((resolve,reject)=>{
setTimeout(()=>{ resolve() },5000)
})
.then(
()=> {
console.log("第二件事情:吃早餐")
}
)
await new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve()
},1000)
})
.then(
()=> {
console.log("第三件事情:上课")
}
)
console.log("第四件事情:下课");
}
speaking();
// 总结:
// async 关键字修饰的函数,可以返回promise实例。
// await 关键字必须在async函数作用域中使用,而且需要结合promise语法,才有“等待”的作用。
// 应用场景:
// 比如:首先渲染html字符串,然后操作html标签。
类 class (面向对象)
面向对象
概念
是一种编程思想(指导程序开发程序的思想),与面向过程相反。面向对象是判断软件好与坏的标准。
面向过程:步骤比较清晰(第一步获取标签,第二步绑定事件,第三步书写业务逻辑)
面向对象: 围绕对象成员实现不同功能 (通过this添加属性,通过原型添加方法,从而构建一个对象出来)
特性
封装性:把客观存在的数据添加到对象中(把实现业务逻辑的代码写在函数或对象中)
继承性:A对象(子)可以拥有B对象(父)的属性和方法 (代码复用)
多态性: 同一个对象或函数,在不同的场景下,可以有不同的表现形式。
抽象
抽象的事物有哪些?
比如:
车
人类
动物 ....
App构造函数(抽象的)
类 (class)
具体
具体的事物有哪些?
比如:
科技园楼下的红色大众汽车
前端就业班2429班的毅明班长
App实例对象
ES5 中面向对象的写法有很多种。。。。
直接量对象
工厂模式
构造函数
原型
apply call bind 改变this指向
....
class的使用
ES6 中的写法比较统一
都是围绕着 class 进行编写
// 设计对象 汽车 Car
// 属性: 品牌(brand) 颜色(color) 价格(price)
// 方法: 展示信息的方法(showInfo)
// 编码:
// 声明类 (抽象)
class Car {
// 这个词汇是固定的(构造函数)
constructor(brand , color , price){
// 添加属性
this.brand = brand;
this.color = color;
this.price = price;
}
// 方法直接在类内部编写即可 (实际上这个方法就是在原型上添加)
// 此处方法名称是自定义的
showInfo(){
console.log(`${this.price}价格的${this.color}的${this.brand}品牌汽车`)
}
}
// 创建类的实例(具体的)
const c1 = new Car("宝马","黑色","30万");
c1.showInfo();
// 类(对象)
// 声明子类
class DaZhong extends Car {
// 构造函数
constructor(brand , color , price){
// 通过父类函数接收参数
super(brand , color , price);
}
}
// 创建子类实例
const d1 = new DaZhong("辉腾","红色","20万");
d1.showInfo();
静态成员
// class
// 提供静态成员(静态属性和静态方法),意思是由类对象直接使用的属性和方法
// 静态属性和静态方法不是给类的实例对象使用,而是给类直接使用
// 静态属性和静态方法
// 示例2: 声明类
class App2 {
// static 修饰符
// 静态属性
static version = "v1.0.0";
// 静态方法
static showVersion() {
// 是由类来引用属性,叫静态属性
console.log(App2.version);
}
static updateVersion(version) {
App2.version = version;
}
}
// 这是app2是实例对象,其他没有静态成员
// const app2 = new App2();
// console.log(app2);
// 观察类 App2
// console.dir(App2);
// 这些由类直接使用的方法叫静态方法
App2.updateVersion("版本v5.0.0")
App2.showVersion();
私有属性
// 私有属性:只能在当前类内部使用的属性
class App {
// 带有 “#” 符号修饰的属性叫做私有属性,只能在类的内部使用。
#version="v1.0.0";
showVersion(){
console.log(this.#version);//输出版本
}
updateVersion(version){
this.#version = version;
}
}
const app = new App();
app.updateVersion('v6.0.0');
app.showVersion();
// console.log(app.version);// undefined
// console.log(app.#version);//报错,私有属性不能在类的外部使用
模块化
<script>
// 模块化语法,通常是在web工程化项目中使用。(可以webpack构建web工程)
// 现在我们并没有构建web工程,怎么演示使用这个模块化?
// 可以给script标签 设置type属性等于module
</script>
<script type="module">
// 1) 按需导入
import { search , comp1 , comp2 } from './components/Search.js';
search();
// comp1();
// comp2();
// 2) 全部导入
import listObj from './components/List.js';
listObj.init();
// 3)导入 (可以修改模块名称)
import { audioPlayer } from './components/Player.js';
audioPlayer.render();
</script>
// 定义函数 代表搜索组件
// 导出搜索模块
export const search = function(){
let div = document.createElement("div");
div.innerHTML = `<h3>搜索组件</h3>`;
document.body.appendChild(div);
}
// 导出模块1
export const comp1 = function(){
let div = document.createElement("div");
div.innerHTML = `<h3>组件1</h3>`;
document.body.appendChild(div);
}
// 导出模块2
export const comp2 = function(){
let div = document.createElement("div");
div.innerHTML = `<h3>组件2</h3>`;
document.body.appendChild(div);
}
// 导出模块
export default {
// 初始化
init(){
let div = document.createElement("div");
div.innerHTML = `<h3>列表组件</h3>`;
document.body.appendChild(div);
}
}
// 定义对象
const obj = {
render(){
let div = document.createElement("div");
div.innerHTML = `<h3>播放器组件</h3>`;
document.body.appendChild(div);
}
}
// 导出组件时,修改组件的名称
export { obj as audioPlayer };