为了账号安全,请及时绑定邮箱和手机立即绑定

JavaScript创建对象之ES6的Class

使用ES6中的class创建对象

ES6引入了 Class(类)这个概念,作为创建对象的模板。

创建对象之构造函数那篇手记中(JavaScript创建对象之构造函数),我们知道创建对象的最佳方式就是组合使用构造函数和原型,其实,ES6 的class可以看作构造函数+原型创建对象的另一种写法,除了写法更符合面向对象编程的语法之外,并没有实质性的改变。

例子:

构造函数+原型

//构造函数
function Obj(name, age) {
    this.name = name;
    this.age = age;
    //原型对象
    if (typeof(this.getName) != "function") {
        Obj.prototype.getName = function() {
            return this.name;
        }
    } else if (typeof(this.job) != "string") {
        Obj.prototype.iob = "IT";
    }
}

//实例
var p1 = new Obj("Tom", 20);

//测试
console.log(p1.age);
console.log(p1.getName());
//输出:20,Tom

ES6 的 class

//构造函数
class Obj {
    //原型对象上的方法
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    job() {
        return "IT";
    }
    getName() {
        return this.name;
    }
}

//实例
var p1 = new Obj("Tom", 20);

//测试
console.log(p1.age);
console.log(p1.getName());
console.log(typeof(Obj));
//constructor属性指向其构造函数
console.log(p1.constructor == Obj);
//__proto__属性指向其原型
console.log(p1.__proto__ == Obj.prototype);
//输出:20,Tom,function,true,true

重点解析之使用表达式定义Class

从上面的代码测试中可以看到:ES6中的class的数据类型是函数(构造函数也是函数),因此与函数一样,class也可以使用表达式的形式定义。

例子:

var Obj = class {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    job() {
        return "IT";
    }
    getName() {
        return this.name;
    }
}

//实例
var p1 = new Obj("Tom", 20);

//测试
console.log(p1.age);
console.log(p1.getName());
console.log(typeof(Obj));
//输出:20,Tom,function

class表达式的变量名与class的类名可以同时存在,但此时class的类名只在class的内部代码可用,指代当前class;而class表达式的变量名可以在创建实例的时候调用,指代当前class。

例子:

var MyObj = class Obj {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    job() {
        return "IT";
    }
    getName() {
        return this.name;
    }
    getClassName() {
        //注意这里用的是Obj而不是MyObj
        return Obj.name;
    }
}

//实例:注意这里用的是MyObj而不是Obj
var p1 = new MyObj("Tom", 20);

//测试
console.log(p1.getClassName());
console.log(MyObj.name);
//输出:Obj,Obj

如果class的内部没用到class的类名的话,可以省略class的类名。采用class表达式这种写法,可以写出立即执行的class。

例子:

//实例
var p1 = new class {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    job() {
        return "IT";
    }
    getName() {
        return this.name;
    }
}("Tom", 20)

//测试
console.log(p1.age);
console.log(p1.getName());
//输出:20,Tom

重点解析之Constructor方法

在创建class的同时,也会默认为这个class创建constructor方法。这个方法就算没有显式定义,一个空的constructor方法也会被默认添加。constructor方法默认返回实例对象的属性(写在this上的属性),与写在构造函数里面的this属性有相同效果。

例子:

//实例
var p1 = new class {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    job() {
        return "IT";
    }
    getName() {
        return this.name;
    }
}("Tom", 20)

//测试
//hasOwnProperty()方法用于检测实例对象的属性是写在实例上(返回true),还是继承自原型上(返回false)
console.log(p1.hasOwnProperty("name"));
console.log(p1.hasOwnProperty("constructor"));
console.log(p1.hasOwnProperty("job"));
console.log(p1.hasOwnProperty("getName"));
//输出:true,false,false,false

通过上面例子的测试,可以发现:class内部的方法都是定义在原型对象上面,而constructor方法也同样如此,但是它返回的是实例对象的属性。既然class的所有方法都默认定义在class的原型属性上面,那我们就可以使用Object.assign方法一次性向class添加多个方法。

例子:

class Obj {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
}

Object.assign(Obj.prototype, {
    job() {
        return "IT";
    },
    getName() {
        return this.name;
    }
});

//实例
var p1 = new Obj("Tom", 20);

//测试
console.log(p1.job());
console.log(p1.getName());
//输出:IT,Tom

class中定义的所有方法,都会被实例继承。但是如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是只能通过class来调用,这称之为“静态方法”。静态方法中的this关键字指向class本身,而不是实例。另外,class内部只有静态方法,没有静态属性。

例子:

class Obj {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    static job() {
        return "IT";
    }
    static getName() {
        return this.name;
    }
}

//实例
var p1 = new Obj("Tom", 20);

//测试
console.log(p1.age);
console.log(Obj.getName());
//输出:20,Obj

最后,class必须使用new调用,否则会报错。

class与对象字面量的相似之处

class与字面量的相似之处不仅仅定义class的语法类似于对象字面量的简写形式,class还有以下两点与对象字面量类似。

1、class也支持定义访问器属性

例子:

let person = new class {
    constructor(name, age) {
        this.name = name;
        this.age = age;
        this._family = "mama";
    }
    get family() {
        return this._family;
    }
    set family(v) {
        this._family = v;
    }
    getName() {
        return this.name;
    }
}("Tom", 19);
console.log(person.family); //输出:mama
person.family = "baba";
console.log(person.family); //输出:baba
console.log(Object.keys(person)); // 输出:["name", "age", "_family"]

*class中所有方法默认都是不可枚举的,因此使用get和set关键字定义的属性也是不可枚举的。

2、class也支持用表达式定义或访问属性

例子:

let fn = "getName";
let person = new class {
    constructor(name, age) {
            this.name = name;
            this.age = age;
        }
        [fn]() {
            return this.name;
        }
}("Tom", 19);

console.log(person[fn]()); //输出:Tom
console.log(person["getName"]()); //输出:Tom

文中的代码部分,带有“例子”和“测试代码”字样的,只是用来学习或测试某一功能用的代码,不可以直接用于项目的开发中。带有“代码如下”字样的,都是经过本人测试,简单修改即可用于项目开发中的代码,如有错误,欢迎指出。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消