Skip to content

JavaScript 精髓之原型对象 #9

@ilcherry

Description

@ilcherry

在面向对象编程中, 类是一种面向对象计算机编程语言的构造,是创建对象的蓝图,描述了所创建的对象共同的属性和方法。 ——《维基百科》

简而言之,类是对象属性和方法的封装

在传统面向对象语言中,以 Java 为例。Java 是一门传统的纯面向对象语言。

public class Person {
  String name;

  void showName() {

  }
}

原型

JavaScript 是一门弱面向对象多范式的动态类型语言。它没有提供传统面向对象语言中的类式继承,而是通过原型对象实现对象与对象之间的继承。

JavaScript 中的对象有一个特殊的 __proto__ 内置属性,其实就是对于其他对象的引用。
几乎所有的对象在创建时 __proto__ 属性都会被赋予一个非空的值。

在面向类的语言中,类可以被复制(或者说实例化)多次。但是在 JavaScript 中,并没有类似的复制机制,
不能创建一个类的多个实例,只能创建多个对象,它们的 __proto__ 关联的是同一个对象。
但是在默认情况下并不会进行复制,因此这些对象之间并不会完全失去联系,它们是相互关联的。

const Person = function(opt) {
  this.name = opt.name;
  this.age = opt.age;
};

Person.prototype = {
  constructor: Person,
  showName() {
    return this.name;
  }
};

const xiaoming = new Person({ name: "xiaoming", age: 18 });
const xiaohua = new Person({ name: "xiaohua", age: 18 });

在 JavaScript 中, 我们并不会将一个对象('类')复制到另一个对象(实例),只是将它们关联起来。

继承

库中的使用

我们来看看在 underscore.js 中的应用

// underscore.js v1.9.2

var _ = function(obj) {
  /* 
      obj 为 new _() 的情况,直接返回该实例
    */
  if (obj instanceof _) return obj;
  /* 
      当开发者使用 _([]) 这样的模式,
    */
  if (!(this instanceof _)) return new _(obj);
  /* 
      其它情况下, 将 obj 参数赋值给 _wrapped 属性
    */
  this._wrapped = obj;
};

当我们以 _([1,2,3]) 方式使用 underscore.js 时,就把 _ 函数当做构造函数(即创建名为 _ 的"类"),
同时它的 __proto__ 指向它的原型对象 _.prototype。准确来讲,关联它原型对象上的属性和方法。

再看看 _.prototype 上定义的属性和方法。

// underscore.js v1.9.2

_.mixin = function(obj) {
  _.each(_.functions(obj), function(name) {
    var func = (_[name] = obj[name]);
    _.prototype[name] = function() {
      var args = [this._wrapped];
      push.apply(args, arguments);
      /* 
          最后都要返回 _ 实例,才能启用链式调用
          this 指向 _.prototype
        */
      return chainResult(this, func.apply(_, args));
    };
  });

  /* 
      _ 是一个类
    */
  return _;
};

_.mixin(_);

在 _.mixin 函数的体内,通过 _.each 方法将 _ 函数(此时作对象使用)上的方法添加到 _.prototype 对象上,
由此,所有的 _ 实例均可以关联原型对象上的属性和方法。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions