es6类class
程序员文章站
2022-03-08 22:16:46
...
es5之前定义对象类
function Person(name,age){
this.name = name
this.age = age
}
Person.prototype.showName = function(){
console.log(this.name)
}
Person.prototype.showAge = function(){
console.log(this.age)
}
或
Object.assign(Person.prototypr,{
showName = function(){
console.log(this.name)
},
showAge = function(){
console.log(this.age)
}
})
let p = new Person("张三",18)
p.showName()
p.showAge()
es6 采用关键字class来定义类:
class Person{
constructor(name,age){ // 构造函数,只要调用了new 就会执行这个函数
console.log("构造函数执行了")
this.name = name
this.age = age
}
//注意:方法之间不能有逗号,他不是一个json,是有一个类
showName(){
console.log(this.name)
}
showAge(){
console.log(this.age)
}
}
或表达式定义class类:
const Person = class{
constructor(name,age){ // 构造函数,只要调用了new 就会执行这个函数
console.log("构造函数执行了")
this.name = name
this.age = age
}
showName(){
console.log(this.name)
}
showAge(){
console.log(this.age)
}
}
let p = new Person("张三",18)
p.showName()
p.showAge()
es6里面属性名可以放表达式:
let Fun = "showF" // 定义一个变量
class Person{
constructor(name,age){ // 构造函数,只要调用了new 就会执行这个函数
console.log("构造函数执行了")
this.name = name
this.age = age
}
//注意:方法之间不能有逗号,他不是一个json,是有一个类
showName(){
console.log(this.name)
}
showAge(){
console.log(this.age)
}
[Fun](){
console.log("变量方法")
}
}
let p = new Person("张三",18)
p.showF() 等同于 p[Fun]()
也可以使用字符串拼接 [a+b](){} p[a+b]()
注意:1.ES6中class类不支持提升的功能(预解析),在ES5中函数定义的类能够先执行后定义,但是class类只能先定义再执行
2.ES里面的this比之前轻松
矫正this的方法:
1.fn.call(this指向谁,args1,args2....) // 单个传参
2.fn.call(this指向谁,[args1,args2....]) // 数组形式传参
3.fn.bind(this指向谁) // 只进行this矫正,不传参
正常情况下this指向不会发生改变,但是有时候我们会用到ES6解构语法,来获取勒种的方法,name此时this就发生了变化:
class Person{
constructor(name,age){
this.name = name
this.age = age
this.showName = this.showName.bind(this) // 重定向this
}
showName(){
console.log(this.name)
}
showAge(){
console.log(this.age)
}
}
let p = new Person("张三",18)
let{showName} = p;
showName() // 此时使用解构出来的函数会报错,this,解决的方法是在构造函数中,重新定向this,如上。
class里面取值函数getters,存值函数setter:
class Person{
constructor(){
}
get name(){
console.log(`获取了name属性:${this.name}`)
}
set name(){
console.log(`设置了name属性:${this.name}`)
}
}
let p = new Person()
p.name = "张三" // 设置name
console.log(p.name) // 获取name
注:一般用于封装底层的插件才会用到getter和setter
class静态方法:
class Person{
constructor(name){
this.name = name
this.showName = this.showName.bind(this) // 重定向this
}
showName(){
console.log(this.name)
}
static aaa(){ // 声明静态方法,可以在外部通过类对象调用
// 封装插件时用的比较多,比如jQuery.fn()
console.log(`这是静态方法`)
}
}
let p = new Person("张三")
console.log(Person.aaa()) // 如果没有声明静态方法时,这样调用就会报错
类的继承:
之前类的继承:
父类:
function Persong(name){
this.name = name
}
Person.prototype.showName = function(){
console.log(`名字是:${this.name}`)
}
子类:
function Student(name,done){
Person.call(this,name) // 继承父级的属性
this.done = done
}
Student.prototypr = new Persin(); // 继承父级方法(此时需要矫正constructor)
调用:
let stud1 = new Student("小明","读书")
console.log(stud1.showName())
class中的继承:
父类
class Person{
constructor(name){
this.name = name
}
showName(){
console.log(this.name)
}
}
子类
class Student extends Person{ // extends继承
constructor(name,done){
super(name) // 执行父级的构造函数
this.done = done
}
showDone(){
console.log(this.done)
}
}
调用
let stud1 = new Student("小明","读书")
console.log(stud1.showName())
console.log(stud1.showDone())
如果此时子类中有一个方法名与父级重名,那么会覆盖父级的方法,可以在子类的方法中执行以下父级的方法:
showName(){
super.showName() // 父级的方法执行
console.log("子类的showName")
}
es6继承小例子:拖拽
<html>
<div id="div1">1</div>
<div id="div2">2</div>
</html>
<script>
// 普通拖拽(父类)
class Drag{
constructor(id){
this.oDiv = document.querySelector(id)
this.disx = 0
this.disy = 0
this.init()
}
init(){
this.oDiv.onmouseDown = function(ev){ // 鼠标在元素上按下时
this.disx = ev.clientX - this.oDiv.offsetLeft //鼠标点击时与物体左边的距离
this.disy = ev.clientY - this.oDiv.offsetTop // 鼠标点击时与物体右边的距离
document.onmousemove = this.fnMove.bind(this) // 鼠标移动事件
document.onmouseup = this.fnUp.bind(this) // 鼠标抬起事件
return false; // 阻止默认事件(如:文字选中等)
}.bind(this)
fnMove(ev){
this.oDiv.style.left = ev.clientX - this.disx + "px"
this.oDiv.style.top= ev.clientY - this.disy + "px"
}
fnUp(){null
document.onmousemove = null
document.onmoudown = null
}
}
//限定范围拖拽(子类)
class LimitDrag extends Drag{
fnMove(ev){
super.fnMove(ev) // 继承执行父级鼠标移动的方法
//增加限制范围(只写了水平方向的限制,垂直方向的同理)
if(this.oDiv.style.left<=0){
this.oDiv.style.left = 0
}
if(this.oDiv.style.left>=500){
this.oDiv.style.left = 500 + "px"
}
}
}
// 调用
new Drag("#div1") // 普通拖拽
new LimitDrag("#div2") // 限定范围拖拽
</script>