array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 JavaScript的类和继承 - 爱码网

本文参考了两本书:

<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的情况下,提供明朗的类和继承。

相关文章: