一、构造函数和class
ES6之前,JS生成实例对象通过构造函数
function f(width, height){
this.width = width;
this.height = height
}
f.prototype.getArea = function(){
return this.height*this.width
}
let area = new f(10, 20)
area.getArea() //200ES6,为了更贴近传统面向对象语言的使用方式,引入了类的概念,也就是class。但是class可以看做是一个语法糖,它的实现依然是基于构造函数方式实现的。
ES6中上面的例子可以改写成
class f {
constructor(width, height){
this.width = width;
this.height = height
}
getArea(){
return this.width*this.height
}
}
let area = new f(10, 20)
area.getArea() //200类可以简单地认为是构造函数的另一种写法,是为了更符合面向对象类型编程的思想和方式。因此类的数据类型就是函数,类指向的就是构造函数。同时,类中定义的方法都定义在类的原型上
f.prototype.constructor === f //true
area.getArea === f.prototype.getArea //true
二、class中的getter和setter
可以通过getter和setter监控属性的存取操作
var middle = 0;
class f{
constructor(){}
set width(val){
console.log('设置width的值=', val)
middle = val
}
get width(){
console.log('获取width的值')
return middle
}
}
let o = new f(middle)
o.width = 10 //设置width的值= 10
o.width //获取width的值 10
三、静态方法
静态方法表示不会被实例对象继承的方法,可以直接通过 className.functionName 调用。
和其它语言一样,静态方法也通过 static 定义。
class Student{
static setStudent(name, age){
return `姓名:${name};年龄:${age}`
}
static getStudent(){
return this.setStudent('小明', 18)
}
}
Student.getStudent() //"姓名:小明;年龄:18"
let student = new Student()
student.getStudent() //Uncaught TypeError: student.getStudent is not a function
从上面的例子可以看到,如果通过实例对象访问类中的静态方法,会报错。通过Student.getStudent() 访问时,方法内的 this 指向的是 Student 类。
四、静态属性
class本身的属性,不定义在this上,不会被实例对象继承。
ES6规定,class内部只有静态方法,没有静态属性。
因此,在ES6中定义静态属性只能在类外通过 className.attrName 定义。
class Student{
constructor(){
this.name = '小明'
}
}
Student.school = '北京大学'
let student = new Student()
console.log(student.name); //小明
console.log(Student.school); //北京大学
console.log(student.school); //undefined但是目前有关于静态属性相关提案,可以通过static关键字定义静态属性,并且此方法也已经在部分浏览器实现,具体可查看 MDN文档
五、class中的this指向
JS中的this指向问题真是千年狐妖,“魅惑”众生啊。
class中的this默认情况下指向的都是类的实例,但是某些情况下也会生变
class Student{
constructor(name, age){
this.name = name;
this.age = age
}
getStudent(){
console.log(this)
}
}
let student = new Student('小明','18')
student.getStudent() //Student {name: "小明", age: "18"}
let printStudent = student.getStudent
printStudent() //undefined通过上面的例子可以看到,使用实例对象正常去调用 getStudent() 方法,得到的this指向的就是对象本身。但是如果将 getStudent() 赋值给一个变量,再通过变量调用,this指向的就是当前方法运行所在的环境,因为class运行在严格模式下,所以this指向undefined。
当然,class中的函数单独使用this指向的问题可以通过 bind() 进行手动绑定或者使用箭头函数定义(箭头函数中的this总是指向定义是所在的对象,后续不会改变)。但是在实际使用中还是要避免这种方式使用class中的方法。