每日JavaScript -10(class)

本文深入解析ES6中引入的Class语法,从基本定义到构造函数,再到类的属性和方法,详细阐述了如何使用Class创建对象,以及Class与传统构造函数的区别。同时,探讨了类的私有属性实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前说过ES6引入class(类)这个概念,那我们赶快来学习一番吧。
http://es6.ruanyifeng.com/#docs/class 这是阮一峰老师的ES6入门书,我觉得是学习ES6必看的书,而且它在网络开源,非常了不起,给阮一峰老师点赞。
这篇文章就是阅读上面文章的简单笔记,话不多说开始。
怎么使用class?

//定义类
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}

可以看到每个class都有一个constructor(构造函数),使用new操作会默认调用construcor生成实例。
下面可以看到 toString()不用再加: 和 function,大括号直接写函数定义。

class Point {
  // ...
}

typeof Point // "function"
Point === Point.prototype.constructor // true

这段代码表示类的数据类型就是函数,类的constructor指向类自身。

class Point {
  constructor() {
    // ...
  }

  toString() {
    // ...
  }

  toValue() {
    // ...
  }
}

// 等同于

Point.prototype = {
  constructor() {},
  toString() {},
  toValue() {},
};

阮老师进一步揭示类的方法都是定义在的类的原型上(这就如同原型模式一样)。
因此,我们使用Object.assgin()可以一次为对象添加多种方法

class Point {
  constructor(){
    // ...
  }
}

Object.assign(Point.prototype, {
  toString(){},
  toValue(){}
});

类必须包括constructor,否则JavaScript会为它创建一个空的constructor
类与普通构造函数一个主要区别在于,类必须由new调用,自己不能执行,而普通构造函数能自己执行

class Foo {
  constructor() {
    return Object.create(null);
  }
}

Foo()   // error

实例显示定义在其自身,否则都是定义在原型上(即定义在class上)。

//定义类
class Point {

  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }

}

var point = new Point(2, 3);

point.toString() // (2, 3)

point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true

再复习一次__proto__是实例的一个属性,指向构造函数或者class的原型。在这里,阮老师更深入介绍了这个属性。
_proto_ 并不是语言本身的特性,这是各大厂商具体实现时添加的私有属性,虽然目前很多现代浏览器的 JS 引擎中都提供了这个私有属性,但依旧不建议在生产中使用该属性,避免对环境产生依赖。生产环境中,我们可以使用 Object.getPrototypeOf 方法来获取实例对象的原型,然后再来为原型添加方法/属性。

var p1 = new Point(2,3);
var p2 = new Point(3,2);

p1.__proto__.printName = function () { return 'Oops' };

p1.printName() // "Oops"
p2.printName() // "Oops"

var p3 = new Point(4,2);
p3.printName() // "Oops"

上面代码,表明可以通过实例的__proto__为类添加方法,因为它指向class的prototype啊。
class的表达式

const MyClass = class Me {
  getClassName() {
    return Me.name;
  }
};

注意这个类名是叫Myclass。me的作用就是替代this而已。

采用 Class 表达式,可以写出立即执行的 Class。

let person = new class {
  constructor(name) {
    this.name = name;
  }

  sayName() {
    console.log(this.name);
  }
}('张三');

person.sayName(); // "张三"

类不会有变量提升

{
  let Foo = class {};
  class Bar extends Foo {
  }
}

上面的代码不会报错,因为Bar继承Foo的时候,Foo已经有定义了。但是,如果存在class的提升,上面代码就会报错,因为class会被提升到代码头部,而let命令是不提升的,所以导致Bar继承Foo的时候,Foo还没有定义。

类的私有属性
很遗憾,ES6不提供。阮老师提到一种使用symbol的方法来模拟实现。因为我不懂symbol,日后再来介绍,先放代码。

const bar = Symbol('bar');
const snaf = Symbol('snaf');

export default class myClass{

  // 公有方法
  foo(baz) {
    this[bar](baz);
  }

  // 私有方法
  [bar](baz) {
    return this[snaf] = baz;
  }

  // ...
};

暂时先介绍到这里,后面一些内容有点难,我需要整理一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值