本文参考了两本书:
<JavaScript: The Good Parts>(JSTGP) by Douglas Crockford
<JavaScript Web Application> (JSWA) by maccman
如何在JavaScript中使用”类“,W3CSHOOL提供了一个貌似不错的解决方案,也就是所谓的PseduoClassical范式:
var Person = function (opt) { opt = opt ? opt : {}; this.name = opt.name; }; Person.prototype.hello = function() { console.log("hello, I'm " + this.name); }; var Programmer = function (opt) { opt = opt ? opt : {}; Person.apply(this, arguments); this.language = opt.language; }; Programmer.prototype = new Person(); Programmer.prototype.coding = function() { console.log("I'm coding with " + this.language); }; var lucy = new Person({name: "lucy"}); lucy.hello(); var jack = new Programmer({name: "jack", language: "JavaScript"}); jack.hello(); jack.coding();
一切都很熟悉,类有了,继承也很明朗。只是你可能感到疑惑,
*为什么一个类要使用function关键字来定义呢?
*这一句:Programmer.prototype = new Person(); 显得有些别扭,它是如何实现继承关系的?
这是因为,new操作符实际上是JavaScript对面向对象程序员的一种妥协。它做的工作,就是,以Function的prototype为模板创建并返回一个新对象。在JSTGP的Function一章里,给出了如果new的方法实现版本:
Function.prototype.new = function() { var that = Object.create(this.prototype); var object = this.apply(that, arguments); return (object && typeof object === 'object') ? object : that; //如果你用来定义“类”的function有返回值,那么返回该值,一般你不会这么做 }; ... var lucy = Person.new({name: "lucy"});
为什么用function关键字来定义类呢?实际上初学者有一个误区,对prototype chain的误解,看看下面的代码:
var lucy = Person.new({name: "lucy"}); lucy.hello(); var nobody = {}; nobody.prototype = lucy; nobody.hello();TypeError: Object #<Object> has no method 'hello'
这段代码的问题就是,认为prototype是对象的一个属性,设置了prototype之后,nobody的hello方法就会向上寻址。实际上,prototype是function的一个属性,而它的存在,只是为了上文提到的new操作的抽象。虽然可以说,JavaScript的new操作大致上像其他语言一样是按照模板来创建实例。但是一个显著的不同是,例如c#,一个新对象必须通过new创建,而JavaScript则不然,在上例中,是通过Object.create创建的,而new操作反而是一个语法糖(Sugar),另外,你也能够很容易的通过var a = {};这样的语句来创建一个对象。
JavaScript是一种Prototype Based Language,而不是Class Based Language。本质区别是,Class Based Language的类是静态的,也就是说,一个对象的能力是静态的,而Prototype Based Language的对象的能力是动态的。可以说,JavaScript天然没有类,因而天然没有继承。而JSTGP更是指出,new是JavaScript设计中的缺陷,不要使用new。下面介绍Functional范式,在不使用new的情况下,提供对象模板:
var person = function (name) { var that = {}; that.sayHello = function () { console.log("Hello, my name is " + name); }; return that; }; var programmer = function (name, language) { var that = person(name); that.code = function () { console.log("I'm coding with " + language); }; return that; };
这种范式有一个好处,就是可以拥有私有成员,因为定义的方法可以访问函数作用域;而一个不好的地方就是,它的每个实例都会有自己的独立的方法,造成了内存的比较大的消耗。
但是面向对象的概念有助于大型软件的开发,在下一篇文章里,我们将讨论一种巧妙的范式,在不使用别扭的new的情况下,提供明朗的类和继承。
来源:https://www.cnblogs.com/zhengwenwei/archive/2012/11/14/2770412.html