资讯专栏INFORMATION COLUMN

再和“面向对象”谈恋爱 - class(四)

刘东 / 964人阅读

摘要:在上一篇文章里我介绍了一下面向对象编程的概念,在最后终于喜出望外看到了提供了类的概念了。而到了里面真正的类与构造函数现在是分离的,通过上面的代码可以看出来,这种写法正是面向对象的正统写法。

在上一篇文章里我介绍了一下面向对象编程的概念,在最后终于喜出望外看到了ES6提供了类的概念了。那这个类如何去用,是这篇文章的主题。ES6给我们提供了一个class关键字。这个关键字跟以前的var let const很像,它们都是用做声明的,而class就是用来声明一个类的。

语法
class name [extends]{   //extends是用来继承的,可选参数
    //class body
};

注意

class不能重复声明(与let、const一样)

类的本质还是一个构造函数

class Div{  //类
    constructor(x,y){   //构造函数
        this.x=x;    //共享属性,放在constructor里
        this.y=y;
    }//注意这里是没有逗号的
    move(){    //共享方法,这里相当于在Div.prototye上添加方法
        console.log("动起来");
    }
}
console.dir(Div);   //在控制台里看一下与ES5的面向对象程序有什么不同

ES5里面的面向对象,所谓的“类”与构造函数其实是一个东西,也就是双重角色。而到了ES6里面真正的类与构造函数现在是分离的,通过上面的代码可以看出来,这种写法正是面向对象的正统写法。同时,我们在控制台里看到这个对象与ES5的对象区别仅在于显示的名字上多了一个class关键字,如下图:

下面我要详细的对比一下ES5ES6的面向对象有什么区别,以及用这种方式写出来的对象与ECMAScript的内置对象有什么区别,这样做的目的能让你清晰的明白面向对象编程究竟是一种什么样的形式。

1、与ES5对比
const [div1,div2]=[new Div(10,20),new Div(15,20)];    //这两个对象是为了对比他们身上的原型
div1.z=30;    //给实例添加一个私有属性

console.log(
    typeof Div,    //function 构造函数(虽说是类,但实质还是构造函数)
    Div.prototype.constructor===Div,    //true 类本质还是构造函数(披着羊皮的狼)
    
    //Object.getPrototypeOf方法是用来取对象身上的原型,用它代替__proto__
    Object.getPrototypeOf(div1)===Div.prototype,    //true 实例的原型就是构造函数的原型
    Object.getPrototypeOf(div1)===Object.getPrototypeOf(div2),  //true 两个实例的原型都一样,指向构造函数的原型对象
    
    div1 instanceof Div,        //true div是它的实例
    div1.constructor===Div,        //true 实例的构造函数就是类
    
    /*
     * 方法说明
     *  Object.getOwnPropertyNames()这个方法是用来获取对象身上的所有属性名
     *  hasOwnProperty()用来判断某个属性是对象自身的(true),还是继承自原型对象的(false)
     *  Object.keys()返回对象所有可枚举(遍历)的属性名
     */
    Object.getOwnPropertyNames(div1),//["x", "y", "z"] 实例自己的属性
    div1.hasOwnProperty("x"),        //true 实例的属性
    div1.hasOwnProperty("move"),    //false 这个方法是继承而来的
    Object.keys(Div.prototype)        //[] 对象身上的方法都是不可枚举的
);

//ES5定义的对象,身上的方法是可以枚举的
function Car(){}
Car.prototype.drive=function(){
    console.log("窜的老快了");
}
console.log(Object.keys(Car.prototype));  //["drive"] 所有方法都是可枚举的

从上面的代码得出以下的结论

类的本质还是构造函数,其实class就是个语法糖,它的内部还是个构造函数

class声明的对象与ES5声明的对象实质上一样

class声明的对象,它身上的方法都不能被枚举

2、与内置对象对比
const [d1,d2]=[new Date(),new Date()];  //声明两个内置对象实例
d1.x=10,d1.y=20,d1.z=30;    //给实例添加三个私有属性

console.log(
    typeof Date,    //function
    Date.prototype.constructor===Date,    //true
    Object.getPrototypeOf(d1)===Date.prototype, //true
    Object.getPrototypeOf(d1)===Object.getPrototypeOf(d1),  //true
    d1 instanceof Date, //true
    d1.constructor===Date,  //true
    Object.getOwnPropertyNames(d1), //["x", "y", "z"]
    d1.hasOwnProperty("x"),  //true
    d1.hasOwnProperty("getDate"),   //false 这个方法是继承于Date对象的
    Object.keys(Date.prototype),    //内置对象身上的方法都是不可枚举的
);

从上面的代码得出以下的结论

自定义对象就是我们声明的一个类似于内置对象的对象

JavaScript的面向对象编程,实质是把某个功能写成一个对象,并且这个对象是在模仿内置对象

添加属性与方法

class声明的对象同样允许小伙伴们任性的添加属性与方法,包括共享与私有的。

共享属性放在constructor里,共享方法放在大括号内

私有属性放在类身上,私有方法放在大括号内同时前面要加static关键字

私有方法里this指向类本身,其它方法里的this指向实例对象

class Bear{
    constructor(){
        this.name="熊大";   //共享属性(放在constructor里)
    }
    sleep(){    //共享方法(直接放在大括号里)
        this.name="熊二";    //this指向实例,所以在这里给this添加属性还是实例的属性
        console.log(`${this.name}爱睡觉`);
    }
    static gohome(){    //私有方法
        //类会默认添加一个name属性,值为class后面的那个单词
        console.log(`${this.name}的家在森林`);  //这里的this并不会指向实例,而是指向类
    }
}

//共享属性与方法
const b1=new Bear();
console.log(b1.name);    //熊大    
b1.sleep();    //熊大爱睡觉
console.log(b1.name);    //熊二  sleep里重新定义了name属性,所以在这就被改了

//私有属性与方法
Bear.age=5;        //在外面添加私有属性
console.log(b1.age);    //undefined 实例不具备
Bear.gohome();            //Bear的家在森林
//b1.goHome();            //报错,它是私有方法

下篇文章会详细介绍class里的继承。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96657.html

相关文章

  • 再和面向对象恋爱 - 图片预加载组件(七)

    摘要:源码下载至此再和面向对象谈恋爱系列文章已经全部更新完毕写文章不易,且行且珍惜 再和面向对象谈恋爱 - 对象简介(一)再和面向对象谈恋爱 - 对象相关概念(二)再和面向对象谈恋爱 - 面向对象编程概念(三)再和面向对象谈恋爱 - class(四)再和面向对象谈恋爱 - 继承(五)再和面向对象谈恋爱 - super(六) 通过前面的六篇文章已经把ES6的面向对象跟大伙说清楚了,大家最关心的...

    caoym 评论0 收藏0
  • 再和面向对象恋爱 - 面向对象编程概念(三)

    摘要:说到底面向对象才是程序语言的根本。其实面向对象编程说的就是自定义对象。里并没有类的概念,所以严格上来讲这是个假的面向对象里的面向对象编程现在好了,终于听到别人鄙视我们了,给我们提供了类这个概念,其实是向传统语言更靠齐了。 通过前两篇文章,我们了解了对象的概念以及面向对象里的相关概念等知识,那前面说了对象分类里的前两种,这篇文章要详细去说第三种自定义对象,那真正的好戏这就来了! 面向对象...

    Cruise_Chan 评论0 收藏0
  • 再和面向对象恋爱 - super(六)

    摘要:同时弹出的结果是指向了子类,又说明虽然调用的是父类的构造函数,但是调用完后会指向子类,指向也被改成了子类的实例。 在上一篇文章里介绍了继承,那其中说过一个很关键的东西想要继承子类里里必需先调用一个super方法。而super的作用绝对是价值连城!同时super的作用还有多种,并且跟你的使用环境有关系。 1、当作函数使用 super被当作函数使用,这种情况是最普遍的,上一篇文章里已经使用...

    Towers 评论0 收藏0
  • 再和面向对象恋爱 - 继承(五)

    摘要:面向对象里最大的特点应该就属继承了。在第二篇文章里说过原型实例跟构造函数之间的继承,并且还讲了一道推算题。 通过上一篇文章想必各位老铁已经熟悉了class了,这篇文章接着介绍继承。面向对象里最大的特点应该就属继承了。一个项目可能需要不断的迭代、完善、升级。那每一次的更新你是要重新写呢,还是在原有的基础上改吧改吧呢?当然,不是缺心眼的人肯定都会在原来的基础上改吧改吧,那这个改吧改吧就需要...

    Airmusic 评论0 收藏0
  • 再和面向对象恋爱 - 对象相关概念(二)

    摘要:所有的对象都是由构造函数创建的对象哪来的构造函数生的。而普通函数不能生成对象不孕不育,构造函数可以生成对象有生育能力。别急,记住那句话永远指向实例对象对应的构造函数的,那就先看实例对象是谁。 上一篇文章把对象的概念讲解了一下,这篇文章要重点解释最让大家犯迷糊的一些概念,包括 构造函数 实例 继承 构造函数的属性与方法(私有属性与方法) 实例的属性与方法(共享属性与方法) protot...

    qpwoeiru96 评论0 收藏0

发表评论

0条评论

刘东

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<