在今天在研读《Node.js实践》第九章时,发现了一个以前重来没有考虑到的现象:为对象添加方法的时候,尽然没有加prototype。经过了一番思考和实验,写下了此文作为总结。
关于为对象添加方法时加与不加prototype的区别
目录
一、问题的描述与探究
在今天在研读《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指针不同?
带着这些问题,我做了一些小实验。
首先,在做实验之前,我们知道一些知识:
- 在Javascript中,函数属于Function类型,而Function类型是属于Object类型的,也就是说,函数也是对象。而一个对象中,可以包含一些属性和方法。
- 所有函数的默认原型都是Object的实例。
- 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的方法
用一张图来说明一下关系:
二、引发其他思考
做完实验后,根据实验的结果,引发了一些思考:
- new关键字的原理(参考:MDN)
- 对于“函数”、“构造函数”、“对象”、“原型”、“实例”的概念和关系的重新思考