聊一下对JavaScript中的伪类模式的个人理解

JavaScript中的伪类模式

JavaScript的原型中存在诸多矛盾。某些看起来有点像基于类的语言的复杂语法问题遮蔽了它的原型机制。它不让对象直接从其他对象继承,反而插入了一个多余的间接层,从而使构造函数产生对象。
当一个函数对相被创建时,Function构造器产生的函数对象会运行类似遮掩的一些代码:
this.prototype ={constructor:this};

新函数对象被赋予一个prototype苏花型,其值是包含一个constructor属性且属性值为新函数对象。该Prototype对象是存放继承特征的地方。因为JavaScript语言没有提供一种方法去确定哪个函数是打算用来作结构的,所以每个函数都会得到一个Prototype对象。
constructor属性没什么用。重要的是Prototype对象。当采用构造器调用模式,即使用new前缀去调用一个函数时,这将修改函数执行的方式。如果new运算符是一个方法而不是一个运算符,它可能会像这样执行:

我们也可以定义一个构造器扩充它的原型:

现在我们可以构造一个实例:
我们可以构造另外一个伪类来继承Mammal,这是通过定义它的constructor函数并替换它的prototype为一个Mammal的实例来实现的:

伪类模式本意是想面向对象靠拢,但它看起来格格不入。我们可以隐藏一些不好的细节,这是通过使用method方法定义一个inherits方法来实现的:
我们的inherits和method方法都返回this,这将允许我们可以以级联的样式编程。可以只用一行语句构造我们的Cat:

“伪类”形式可以给不熟悉JavaScript的程序员提供便利,但是也隐藏了该语言的真实本质,借鉴类的表示法可能误导程序员去编写国语深入与复杂的层次结构。许多复杂的类层次结构产生的原因就是静态类型检查的约束。JavaScript完全拜托了那些约束。在基于类的语言中,类的继承是代码重要的唯一方式。JavaScript悠着更多更好的选择。

用原型类的一个小例子来说明一下:

var Car = function(loc) {
var obj = Object.create(Car.prototype);
obj.loc = loc;
return obj;
};
Car.prototype.move = function(){
this.loc++;
};

现在我们把它重构成一种与之相似的模式-伪类模式。称它为伪类,是因为它仿照其他语言中的类系统,试图增添一些语法上的便利,如果我们要在程序中构造大量的类,那将会产生大量的重复代码,而语言本身可以通过某种方式自动实现一些步骤。
看上面这个列子,你认为哪些代码是每个类都需要的并且有可能通过语言实现自动化的呢?没错,就是这两行

var obj = Object.create(Car.methods);
return obj;

每个类都要创建一个对象,并且确保这个对象被委托到原型对象,并且返回这个对象。即这些行为会发生在每一个原型类中。
为了简化输入JavaScript提供了关键字new ,当我们在一个函数调用前使用关键字new,该函数便会以一种特殊的模式--构造模式来运行。在此模式中,JavaScript可以自动完成这些工作。所谓构造模式,及时指解释器在你的代码中嵌入几行操作代码,因为它知道无论何时实例化一个新对象,你都需要这些被自动完成。它会暂时性的使你的函数运行一些额外的代码,即使你从未输入这些代码。这些被插入的代码基本上与你之前再原型类里写的代码一样,那么因为我们在ben的创建的时候使用了关键字new,所以Car的调用会运行这些被插入在开头和结尾的额外操作。

而对于amy的创建,我们并没有使用关键字new 在Car调用的前面,所以并不会插入前面的这些代码。所以此时在相同的程序里,这个类函数会以插入或者未被插入这些代码的方式运行。这些插入的代码不会在你的代码中显示。它们只有在调用前面使用关键字new时,作为这种特殊调用的结果才会被执行。但是即使这里展示了两行代码,一行有关键字new,一行没有关键字new,但是你在写程序时不应如此。你应该决定一个函数是使用new关键字,还是不使用new关键字。它的目的是让你跳过一些你已经做的工作。所以如果你决定使用new,就需要再对代码进行一些必要的重构。

this=Object.create(Car.prototype);
/*...*/
return this;

这行代码创建了一个将原型委托在Car.prototype中的对象,并且赋值给this,后面又返回this。这样即使你没有再程序中写出这行代码,解释器也可以把值赋给关键字this。这非常合理,并且与我们理解的关键字this的使用是一致的,关键字this的用途是作为一种便捷的方式去指代一些面向对象函数调用中的任何目标对象,而 var amy = new Car(1); 这个函数的调用就是面向对象的,其目的是构造一个新的对象。这就非常合理,无论新对象是什么,都能成为关键字this指代的目标。因此重构后的代码

var Car = function(loc) {
this = Object.create(Car.prototype);
this.loc = loc;
return this;
};
Car.prototype.move = function(){
this.loc++;
};

但是需要注意这两行代码只是并不存在的标注,用来告诉我们关键字new做的事情。所以去掉这些标注,我们的代码就变成

var Car = function(loc) {
this.loc = loc;
};
Car.prototype.move = function(){
this.loc++;
};
var amy = new Car(1);
amy.move();
var ben= new Car(9);
ben.move();

这就是构造一个伪类时所需要的代码。
此时在内存的情况

这与之前的原型版本并没有本质的区别,因为伪类仅仅是在之前的原型模式之上,为了写代码方便加了薄薄一层语法糖。那么实际上,这两种模式之间的主要区别是JavaScript引擎实现性能优化的数量,而这些优化是伪类模式所独有的。
我们再来看一下这个代码,这段代码与JS中的其他类模式一样,有两个独立区分的部分,这存在之前的每一个伪类模式、原型模式以及函数共享模式之中。
在第2部分,是指定一个类中的所有实例应该相似的部分,在伪类模式中这些相似的部分一般会被存储为prototype对象的属性。在第1部分,你可以指定每个实例和其他实例之间的不同之处。如果大部分语言,这部分写在构造函数体内,它允许我们指定一个类的实例和另一个这个类的实例之间的不同。所有指定的arm和ben不同是的属性loc都是在构造函数内完成的。了解这两部分代码在每一个类中的存在,对于理解子类的概念非常重要。我下一篇会写伪类子类的概念。


JavaScript中支持多种不同的类模式,那么应该使用哪一种模式或者说哪一种是最好的模式,这么问他并没有答案。作为一门语言,JavaScript并没有鲜明的立场,它更倾向于展现其本质的特征,以便程序员灵活运用。因此并不存在对与错,只是技术和选择上的不同。我们能做的是了解每一种类模式的优点和缺点,来帮我们判断在特定的情况下应该使用哪种模式。
最后,不知道各位程序员对伪类有什么看法,请多多指教。

作者:长梦未央
图片来源:优达学城付费课程
个别文字摘自教学视频老师的讲解

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容