1、类的属性和方法(函数):类可以有属性也没有没有属性,可以有方法也可以没有方法
2、类的属性是放在构造方法中初始化的,若类没有属性,可以不显式定义构造方法,此时,系统会自动生成一个无参的空的构造方法
(1)父类(基类):可以派生子类的类
(2)子类(派生类):由父类派生而来的类
(1)封装性:对象是属性和行为的封装体 —- 数据安全
(2)继承性:子类可以继承父类的属性和方法 —- 代码复用
(3)多态性:同一个消息传递给不同对象,出现的效果不同 —- 应用灵活、可以适应不同的需求
(1)ES5中继承的实现:没有类的概念
a、构造函数:构造函数名就是类名,在ES5中类的继承实际就是构造函数的继承
b、实现:通过call、apply、bind函数来实现构造函数的继承
//1.定义构造函数:基类
function Fatcher(name){
this.name = name
this.age = 45
}
//2.定义构造函数:子类
function Son(name){
/* this代表是上层对象(window),name参数传递个Father构造函数。
等于在Son函数中调用了Father函数:Son就具有了name和age属性(相当于从Father继承了name和age)
*/
Fatcher.call(this,name) //函数劫持,在Son中通过call调用Father构造函数,将参数name传递给Father构造函数
this.height = '178cm' //height是Son自己的属性
this.show= function(){
console.log('姓名:',this.name)
console.log('年龄:',this.age)
console.log('身高:',this.height)
}
}
let son = new Son('赵四')
son.show()
(2)ES6中的继承:通过关键字extends实现
//1.定义父类Fatcher
class Fatcher{
constructor(name,age){
this.name = name
this.age = age
}
fun(){
console.log('我是父类中的方法......')
}
}
//2.定义子类Son,继承自Father类
class Son extends Fatcher{
constructor(name,age){
super(name,age); //调用父类的构造函数
}
hobby(){
console.log('我喜欢篮球')
}
show(){
console.log('姓名:',this.name)
console.log('年龄:',this.age)
}
}
let s1 = new Son('张三',25)
s1.hobby()
s1.show()
s1.fun()
A、super:指向父类。super([参数])表示调用父类的构造函数
B、如果在子类的构造函数中调用父类的构造函数,那么super()必须作为子类构造函数中的第一条语句
在执行子类的构造函数之前必须先执行父类的构造函数(先有父,后有子)
C、方法覆盖(Overwrite):在继承过程中,若父类的某个方法与子类的某个方法同名,则子类方法覆盖父类的同名方法
D、在子类的方法中可以使用super调用父类中的某个方法
E、不允许多继承,只能单继承
多继承:类的直接父类有多个
单继承:类的直接父类只有一个父类
练习1:
(1)定义一个点类(Point),具有x,y两个属性(表示坐标),显示本类信息的show()方法;
(2) 定义一个圆类(Circle)由点类派生,增加一个新的属性半径(radiu),一个计算圆面积的area()方法,和一个同样显示本类信息的show()方法;
(3) 定义一个圆柱体类(Cylinder)由圆类派生,增加一个属性高度(height),一个计算圆柱形体积的方法vol(),一个计算圆柱形表面积的area2()方法,和一个同样显示本类信息的show()方法。
(4)测试:Circle类、Cylinder类的方法
//1.定义Point类
class Point{
constructor(x,y){
this.x = x
this.y = y
}
show(){
console.log(`圆心:(${this.x},${this.y})`)
}
}
//2.定义Circle类,继承自Point
class Circle extends Point{
constructor(x,y,radius){
super(x,y)
this.radius = radius
}
area(){ //圆面积
return Math.PI * this.radius **2
}
length(){ //圆周长
return 2 * Math.PI * this.radius
}
show(){
super.show()
console.log('半径:',this.radius)
console.log('圆面积:',this.area())
console.log('圆周长:',this.length())
}
}
//3.定义Cylinder类,继承自Circle
class Cylinder extends Circle{
constructor(x,y,radius,height){
super(x,y,radius)
this.height = height
}
vol(){ //求圆柱体体积
return super.area() * this.height
}
area2(){ //圆柱体的表面积
return (super.length() * this.height) + (2*super.area())
}
show(){
super.show()
console.log('圆柱体的高:',this.height)
console.log('圆柱体的体积:',this.vol())
console.log('圆柱体的表面积:',this.area2())
}
}
//4.测试
let circle = new Circle(101,200,6)
circle.show()
console.log('--------------------')
let cylinder = new Cylinder(50,50,5,12)
cylinder.show()
三、ES6的模块化管理
(1)Node是什么:
A、浏览器内核有两个引擎:渲染引擎(渲染html、css)、JavaScript引擎(运行JavaScript代码)
B、Node是独立于浏览器的JavaScript的运行环境,通常将Node称为JavaScript的服务器运行环境
a、Node相当于运行JavaScript程序的虚拟机
b、是JavaScript的工具库。Node.js内部采用Google公司的V8引擎
(2)使用Node的原因:有了Node后JavaScript就正式成为一个工程化的语言
(1)设置环境变量的目的:在自定义的目录下运行程序时,操作系统可以找到相应的指令
(1)文件名:主文件名.扩展名
.扩展名的作用是:指定文件的类型
.mp3:音频文件 mpeg-3
.mp4:视频文件 mpeg-4
.jpg .png
(2)模块化的操作:导出(export)、导入(import)
第一步:初始化环境,在存放js文件的文件夹下执行:npm init -y (生成package.json文件)
第二步:在package.json文件中加入:“type”:”module” (表示采用的是ES6的模块化管理方式)
(3)导出 / 导入 一个变量:
//在t1.js文件导出变量
export let userName = '武则天'
//exam.js导入变量
import { userName } from "./t1.js";
console.log(userName)
(4)导出 / 导入 多个变量
//在t1.js中导出多个变量
let userName = '武则天'
let userAge = 75
let userFun = function(){
console.log('Name:',userName)
console.log('Age:',userAge)
}
export { userName,userAge,userFun }
//在exam.js中导入变量
import { userName,userAge,userFun } from "./t1.js"; //导入时必须带文件的扩展名(后缀)
console.log(userName)
console.log(userAge)
userFun()
(5)导入变量时重命名:使用as
//在exam.js中导入变量
import { userName as myname,userAge as myage ,userFun as ftp } from "./t1.js";
console.log(myname)
console.log(myage)
ftp()