JavaScript类

发布时间 2023-06-22 17:13:08作者: 好记心不如烂笔头

1 JavaScript类

  • 每个JavaScript对象都是一个属性集合,相互之间没有任何联系
  • 在JavaScript中也可以定义对象的类
    • 让每个对象都共享某些属性,这种“共享”的特性是非常有用的
      • 类的成员或实例都包含一些属性,用以存放或定义它们的状态
      • 其中有些属性定义了它们的行为(通常称为方法)。这些行为通常是由类定义的,而且为所有实例所共享
    • 在JavaScript中,类的实现是基于其原型继承机制的。如果两个实例都从同一个原型对象上继承了属性,我们说它们是同一个类的实例
    • 如果两个对象继承自同一个原型,往往意味着(但不是绝对)它们是由同一个构造函数创建并初始化的

2 类和原型

  • 在JavaScript中,类的所有实例对象都从同一个原型对象上继承属性。因此,原型对象是 类的核心
  • 如果定义一个原型对象,然后创建一个继承自它 的对象,这就定义了一个JavaScript类
  • 类的实例还需要进一步的初始化,通常是通过定义一个函数来创建井初始化这个新对象
//使用工厂的方法创建对象:返回使用new创建的对象
function inherit(p){
    if(p == null) throw TypeError();
    if(Object.create) return Object.create(p);
    if(typeof p!== 'object'&&typeof p!=='function') throw ypeError();
    function f(){}
    f.prototype = p;
    return new f();
}

//使用工厂方法创建一个对象
function range(from,to){
    var r = inherit(range.methods);
    //这两个属性是不可以被继承的,因为它们不是创建在对象的原型上
    r.from = from;
    r.to = to;

    return r;
}

//在range.methods中定义的那些可共享、 可继承的方法都用到了from和to属性, 而且使用了this关键字,

//为了指代它们, 二者使用this关键字来指代调用这个方法的对象。 任何类的方法都可以通过this的这种基本用陆来读取对象的属性。

range.methods = {
    //如果x在范围内,贝Jj返回true,否则返回false
    //这个方法可以比较数字范围,也可以比较字符串和日期范围
    includes: function (x) { 
        return this.from<= x && x <= this.to;
    }, 
    //对于范围内的每个整数都调用一次f(x),这个方法只可用做数字范围
    foreach: function (f) {
        for (var x = Math.ceil(this.from); x <= this.to; x++) f(x);
    },
}

var r = range(1,3);
r.includes(2); 

3 类和构造函数

  • 在JavaScript中,使用工厂方法定义类不常用
  • 在JavaScript中, 推荐使用构造函数来定义类,构造函数是用来初始化新创建的对象的
    • 使用关键字new来调用构造函数会自动创建一个新对象, 因此构造函数本身只需初始化这个新对象的状态即可
    •  使用关键字new来调用构造函数的一个重要特征是, 构造函数的prototye属性被用做新对象的原型。 这意味着通过同一个构造函数创建的所有对象都继承自一个相同的对象, 因此它们都是同一个类的成员
//构造函数
function Range(from,to){
    //这两个属性是不可以被继承的,因为它们不是创建在对象的原型上
    this.from = from;
    this.to = to;
}
//在range.methods中定义的那些可共享、 可继承的方法都用到了from和to属性, 而且使用了this关键字,
//为了指代它们, 二者使用this关键字来指代调用这个方法的对象。 任何类的方法都可以通过this的这种基本用陆来读取对象的属性。
Range.prototype = {
    //如果x在范围内,贝Jj返回true,否则返回false
    //这个方法可以比较数字范围,也可以比较字符串和日期范围
    includes: function (x) { 
        return this.from<= x && x <= this.to;
    }, 
    //对于范围内的每个整数都调用一次f(x),这个方法只可用做数字范围
    foreach: function (f) {
        for (var x = Math.ceil(this.from); x <= this.to; x++) f(x);
    },
}

var r = new Range(1,3);
r.includes(2); 

3.1 构造函数和类的标识

  • 原型对象是类的唯一标识:当且仅当两个对象继承自同一个原型对象时, 它们才是属于同一个类的实例
  • 初始化对象的状态的构造函数则不能作为类的标识,只有两个构造函数的prototype属性指向同一个原型对象,那么这两个构造函数创建的实例是属于同一个类的
  • 尽管构造函数不像原型那样基础, 但构造函数是类的外在表现 。很明显的,构造函数的名字通常用做类名。更根本地讲,当使用instanceof运算符来检测对象是否属于某个类时会用到构造函数。实际上instanceof运算符并不会检查实例是否是由构造函数初始化而来,而会检查实例是否继承自构造函数的prototype, 不过,instanceof的语法则强化了“构造函数是类的公有标识”的概念