在今天在研读《Node.js实践》第九章时,发现了一个以前重来没有考虑到的现象:为对象添加方法的时候,尽然没有加prototype。经过了一番思考和实验,写下了此文作为总结。

关于为对象添加方法时加与不加prototype的区别

目录

  1. 问题的描述与探究
  2. 引发其他思考

一、问题的描述与探究

在今天在研读《Node.js实践》第九章时,发现了一个以前从来没有考虑到的现象:为对象添加方法的时候,尽然没有加prototype。大概就像下面的例子:

// 构造函数User
function User() {
  // ...
}

User.getId = function(name, fn) {
  // ...
}

一开始,我看着这代码就总感觉怪怪的,其中的 User.getId = ... 不是应该写成 User.prototype.getId = ... 吗???它们有什么区别?

User.getId = ... 这样写又会出现怎样的效果?

这个getId方法会加入到原型链中吗?(通过对象的实例能调用这个方法吗?)

究竟如何调用这个getId()方法呢?

里面的this指针会不会和 User.prototype.getId = ... 中的this指针不同?

带着这些问题,我做了一些小实验。

首先,在做实验之前,我们知道一些知识:

  1. 在Javascript中,函数属于Function类型,而Function类型是属于Object类型的,也就是说,函数也是对象。而一个对象中,可以包含一些属性和方法。
  2. 所有函数的默认原型都是Object的实例。
  3. this指向调用这个方法(函数)的那个对象。

下面是实验代码:

function AA() {
}

AA.prototype.func1 = function() {
    console.log(typeof this);  // "Object"
    console.log(this);  // 返回AA对象
    console.log("我是加了prototype的");
}

// 我们知道,一个对象中,包含了属性和方法
// AA是一个function类型,而function类型其实也属于Object类型,所以func2是函数AA(或者说对象AA)的一个方法
AA.func2 = function() {
    console.log(typeof this);  // "function"
    console.log(this); // 返回AA这个构造函数
    console.log("我没有加prototype");
}

var ins = new AA();

ins.func1();  // 显示"我是加了prototype的"

AA.func2();  // 显示"我没有加prototype"

func2();  // 报错,因为func2()这个方法是对象AA的方法,不是AA对象的实例ins的方法

ins.func2();  // 报错,因为func2()这个方法是对象AA的方法,不是AA对象的实例ins的方法

用一张图来说明一下关系:

图片1

二、引发其他思考

做完实验后,根据实验的结果,引发了一些思考:

  1. new关键字的原理(参考:MDN
  2. 对于“函数”、“构造函数”、“对象”、“原型”、“实例”的概念和关系的重新思考