弄懂这些问题,我们分四步
1.它是什么【明白原理】
2.它跟原来的其他能实现同样功能的区别在哪【找到差异】
3.为什么要用它【本质上区别】
4.怎么再工作中立刻就能想到用它【真正的实际意义】
跟着走第一步:概念:ES6规范中引入的class概念,主要思想是想靠近面向对象编程(有过后端开发经验的会清楚c#,java等面向对象编程 类的三大特性 继承 封装 多态);
再看历史:ES6之前 js函数中有构造函数,构造函数的第一个用处(省略重复性代码)如下图:
> 举个例子,我们要录入一年级一班中每一位同学的个人信息,那么我们可以创建一些对象,比如:
> var p1 = { name: 'zs', age: 6, gender: '男', hobby: 'basketball' };
> var p2 = { name: 'ls', age: 6, gender: '女', hobby: 'dancing' };
> var p3 = { name: 'ww', age: 6, gender: '女', hobby: 'singing' };
> var p4 = { name: 'zl', age: 6, gender: '男', hobby: 'football' };
以上代码出现太多重复性代码,用构造函数去实现如下:
> function Person(name, gender, hobby) {
> this.name = name;
this.gender = gender;
> this.hobby = hobby;
> this.age = 6;
> }
当创建上面的函数以后, 我们就可以通过 new 关键字调用,也就是通过构造函数来创建对象了。
> var p1 = new Person('zs', '男', 'basketball');
> var p2 = new Person('ls', '女', 'dancing');
> var p3 = new Person('ww', '女', 'singing');
> var p4 = new Person('zl', '男', 'football');
> // ...
这是构造函数的第一个用处,再来了解构造函数的第二个知识点--继承原型方法: 在构造函数中定义的 方法 本质上是定义在他们的祖先原型上prototype; 构造函数第三个知识点:this的指向(指向的是本实例对象),我们都知道改变this指向的方式有 :如用箭头函数、bind、apply、call和new(也就是我们的构造函数)
回到我们的class上: 为使JS更像面向对象,ES6版本引入class概念,其基本语法:
class Cat{
constructor(name,age){
this.name = name;
this.age = age;
}
Say(){
return '我的名字是' + this.name;
}
}
var cat1 = new Cat('有鱼',2);
console.log(cat1.Say());//我的名字是有鱼
class本质上就是一个function 是在构造函数的基础上更“漂亮些”,我说的漂亮是指五官轮廓更清晰; class和构造函数的继承上的区别:看下面例子
> // 构造函数
> function Duck(){
> this.duckSinging = function (){
> console.log("嘎")
> }
> }
>
> function bird() {
> this.birdFootNum = function (){
> console.log("只有两只脚")
> }
> }
>
> Duck.prototype = new bird()
>
> let tanglaoya = new Duck()
> tanglaoya.duckSinging() // 嘎
> tanglaoya.birdFootNum() // 只有两只脚
class类的写法:
> class bird {
> constructor(num = 2){
> this.num = num
> }
> birdFootNum(){
> console.log(“`有${this.num}只脚”)
> }
> }
>
> class Duck extends bird {
> constructor(num = 2){
> super(num) // super()就是被继承的对象的constructer
> }
> duckSinging(){
> console.log("嘎")
> }
> }
>
> let tanglaoya = new Duck()
> tanglaoya.duckSinging() // 嘎
> tanglaoya.birdFootNum() // 只有2只脚
相比之下,更建议后者的class写法,更加符合面向对象编程思想。
跟着走第二步:跟能实现相同功能的模块化有什么区别
在我学习class时候,自己一直有一个疑惑,原来用模糊化编程把同一个场景的方法放在一个模块中 不是一样也可以实现所谓的class的概念,我单独写一个模块js export出去,为什么会有class而他们之间的区别到底是什么,下面个人观点来说下他们的区别: 区别一:作用域和this指向
1.模块模式为自执行匿名函数,通过返回值暴露函数作用域中的变量(即闭包),可以访问外部变量,this绑定为隐式绑定。
而构造函数模式,构造函数就是普通函数,只是通过new关键字执行this 绑定的new绑定——创造一个新的作用域并将其this变量绑定到作用于内部。
类可以多态而模块不行(隐式绑定总是由调用位置决定,而自执行匿名函数调用位置总是在声明时确定)。
所以区别有:
1.模块划分一旦确定不可轻易更改,类的声明却没有太多顾及。
2.模块由于闭包有内存管理问题,类没有。
3.模块需要运行,先后顺序很重要,类是函数声明,由于JS自带的函数升级,写在代码的任何位置都是可以的,只要new的时候按顺序就行。
4.大部分现代模块系统都不会多次加载一个模块,但是类可以多次new。
跟着走第三步:为什么要用它,其实回答这个问题再弄懂前面两个问题的后,心中即有个百分之7,8十的答案了
总结一句话:考虑业务场景,功能时 充分利用面向对象的三大特性 封装(复用性,扩展性,独立性) 继承(这种是实际工作中好处很多) 多态(目前js的多态用到的还不是太多) 这里粗略讲下js多态: 多态的实际含义是:同一操作作用于不同的对象上面时,可以产生不同的解释和不同的执行结果。换句话说,就是给不同的对象发送同一消息时,这些消息会根据这个消息分别给出不同的反馈。 多态的思想实际就是把“做什么”和“谁来做”分离开来
字面意思难以理解,直接上代码:
class People{
constructor(name){
this.name = name;
}
sayName(){}
}
class A extends People{
constructor(name){
super(name);
}
sayName(){
console.log('I am A');
}
}
class B extends People{
constructor(name){
super(name);
}
sayName(){
console.log('I am B');
}
}
(new A()).sayName();
(new B()).sayName();
//打印:
/*
I am A
I am B
*/
————————————————