前言
传统的javascript中只有对象,没有类的概念。它是基于原型的面向对象语言。原型对象特点就是将自身的属性共享给新对象。这样的写法相对于其它传统面向对象语言来讲,独树一帜也可以说难以接受!
三大特性
封装 继承 多态性
ES5中的类
ES5中如果要生成一个对象实例,需要先定义一个构造函数,然后通过new操作符来完成
示例:
//构造函数名大写(非强制,但这么写有助于区分构造函数和普通函数)
function Person(name,age) {
this.name = name;
this.age=age;
}
Person.prototype.say = function(){
return "我的名字叫" + this.name+"今年"+this.age+"岁了";
}
var obj=new Person("tom",88);//通过构造函数创建对象,必须使用new 运算符
console.log(obj.say());//我的名字叫tom今年88岁了
构造函数生成实例的执行过程:
1.当使用了构造函数,并且
new 构造函数(),后台会隐式执行new Object()创建对象;
2.将构造函数的作用域给新对象,(即new Object()创建出的对象),而函数体内的this就代表new Object()出来的对象。
3.执行构造函数的代码。
4.返回新对象(后台直接返回);
ES6中的类
ES6引入了
class(类)这个概念,通过class关键字可以定义类。该关键字的出现使得javascript在对象写法上更加清晰,更像是一种面向对象的语言。
之前的代码改为ES6的写法:
class Person{//定义了一个名字为Person的类
constructor(name,age){//constructor是一个构造方法,用来接收参数
this.name = name;//this代表的是实例对象
this.age = age;
}
say(){//这是一个类的方法,注意千万不要加上function
return "我的名字叫" + this.name+"今年"+this.age+"岁了";
}
}
var obj=new Person("laotie",88);
console.log(obj.say());//我的名字叫laotie今年88岁了
由下面代码可以看出类实质上就是一个函数。类自身指向的就是构造函数。所以可以认为ES6中的类其实就是构造函数的另外一种写法!
console.log(typeof Person);//function
console.log(Person===Person.prototype.constructor);//true
以下代码说明构造函数的prototype属性,在ES6的类中依然存在着。
console.log(Person.prototype);//输出的结果是一个对象
实际上类的所有方法都定义在类的prototype属性上。代码证明下:
Person.prototype.say=function(){//定义与类中相同名字的方法。成功实现了覆盖!
return "我是来证明的,你叫" + this.name+"今年"+this.age+"岁了";
}
var obj=new Person("kity",88);
console.log(obj.say());//我是来证明的,你叫kity今年88岁了
当然也可以通过prototype属性对类添加方法。如下:
Person.prototype.addFn=function(){
return "我是通过prototype新增加的方法,名字叫addFn";
}
var obj=new Person("kity",88);
console.log(obj.addFn());//我是通过prototype新增加的方法,名字叫addFn
还可以通过Object.assign方法来为对象动态增加方法
Object.assign(Person.prototype,{
getName:function(){
return this.name;
},
getAge:function(){
return this.age;
}
})
var obj=new Person("kity",88);
console.log(obj.getName());//kity
console.log(obj.getAge());//88
注意:
//ES5可以先使用再定义,存在变量提升
new A();
function A(){
}
//ES6不能先使用再定义,不存在变量提升 会报错
new B();//B is not defined
class B{
}
ES6中的 class继承
- 父类(基类)
- 子类
extends关键字
//class 相当于es5中构造函数
//class中定义方法时,前后不能加function,全部定义在class的prototype属性中
//class中定义的所有方法是不可枚举的
//class中只能定义方法,不能定义对象,变量等
//class和方法内默认都是严格模式
//class声明的类默认首字母大写(不是必须,是为了和方法函数区分开来)
//es5中constructor为隐式属性
//给子类添加属性或者方法的时候必须用super()方法 而且在this之前
//父类
class Person {
name
age
constructor(name, age) {
this.name = name
this.age = age
// console.log(this) //实例化对象
}
say() {
console.log(this) //谁调用就指向谁
return `我是${this.name},我${this.age}岁`
}
}
let p1 = new Person('张三', 18) //通过new 实例化对象
p1.say() //我是张三,我18岁
//子类 通过 extends 继承父类
class Son extends Person {
money
weight
constructor(name, age) {
super(name, age) //通过父类改变this指向,继承父类属性
this.money = 200 //给子类上添加父类没有的属性
this.weight = '180kg'
}
run() {
return `我是${this.name},我正在跑步`
}
}
let p2 = new Son('李四', 20) //实例化对象
console.log(p2.say()) //我是李四,我20岁
console.log(p2.run()) //我是李四,我正在跑步
console.log(p2.money) //200
console.log(p2.weight) // 180kg
注意项:
1.在类中声明方法的时候,千万不要给该方法加上function关键字
2.方法之间不要用逗号分隔,否则会报错
3.`class不存在变量提升`,所以需要先定义再使用。因为`ES6不会把类的声明提升到代码头部`,
但是`ES5`就不一样,`ES5存在变量提升`,可以先使用,然后再定义。