JavaScript中的Objects, Prototypes和Classes

举报
Amrf 发表于 2019/11/22 15:47:23 2019/11/22
【摘要】 日常逛街(一个基于kendoUI的文档在线编辑浏览审核发布管理的网站)看看代码,看到一段代码,很怀念的感觉,最近都不怎么见到这么写的了,可能是用多了npm install了的原因吧...(类似的这种https://github.com/inolen/quakejs/blob/master/lib/directed-graph.js写法)function CommonClassA(){ thi...

日常逛街(一个基于kendoUI的文档在线编辑浏览审核发布管理的网站)

看看代码,看到一段代码,很怀念的感觉,最近都不怎么见到这么写的了,可能是用多了npm install了的原因吧...

(类似的这种https://github.com/inolen/quakejs/blob/master/lib/directed-graph.js写法)

function CommonClassA(){
	this.projectId = null;
	this.aaaLists = null;
	this.aaaObj = {};
	this.cloneaaaObj = {};
	this.aaaUrl = localStorage.contextPath + "/xxx/getAAA.do";
	this.aaasUrl = localStorage.contextPath + "/xxx/getAAALists.do";
}
CommonClassA.prototype={
		getAAA : function(aaa){
			var self = this;
		    $.ajax({
	    	    type : "post",
	    		url  : ...Utils.appendTimeForUrl(self.aaaUrl),
	    		data : JSON.stringify(aaa),
	    		contentType:"application/json",
	    		success : function(data){
	    			...
	    		},
	    		error :function(data){
	    			...
	    		},
	    	});
		},
		getAAALists : function(){
		    var self = this;
			$.ajax({
			    type : "post",
				dataType :"json",
	    		url  : ...,
	    		success:function(data){
	    			...
	    		},
	    		error:function(data){
	    			...;
	    		},
			});
		},	
};
var commonClassA= new CommonClassA();

感觉和直接这么写也没什么区别:

var LibraryVM = {
	$VM__deps:[]
	SUSPENDED: 0xDEADBEEF,
	FindLabels: function (state) {}
}

于是搜了搜prototype和class相关的对比,感觉下面这篇文章写得不错

https://alligator.io/js/objects-prototypes-classes/

摘录如下:

考虑到JavaScript中的几乎所有内容都是对象这一事实,面向对象的JavaScript代码与其他支持对象的语言完全不同。JS对象系统更多地是基于原型的对象系统。

从C ++背景的,我知道的面向对象的编程范式中,及比类和对象如何非常严格的想法应该工作。接触其他语言(如Java)似乎只会进一步确立这个想法。这些语言在对象和类的工作方式上有其自己的语义;对于新用户来说,JavaScript是一个很大的启示。

首先,JavaScript对象的创建方式非常不同。不需要一个类。可以使用new运算符创建对象实例:

let Reptile = new Object() {
 // ...
}

或使用函数构造函数

function Reptile() {
 // ...
}

其次,JavaScript对象非常灵活。传统的面向对象语言仅允许属性修改或属性槽,而JavaScript则允许对象修改其属性和方法。即JavaScript对象同时具有属性和方法槽。

在发现时,我的第一个念头是“是的,自由!”,但这要付出代价-需要了解JavaScript的原型属性。对于希望在JavaScript中实现任何面向对象系统的外观的开发人员来说,原型知识都是必不可少的。

所有JavaScript对象都是从Object构造函数创建的:

Reptile.prototype.doesItDrown = function() {
  if (this.canItSwim) {
    console.log(`${this.name} can swim`);
  } else {
    console.log(`${this.name} has drowned`);
  }
};

并且prototype允许我们向对象构造函数添加新方法,这意味着以下方法现在存在于的所有实例中Reptile

Reptile.prototype.doesItDrown = function() {
  if (this.canItSwim) {
    console.log(`${this.name} can swim`);
  } else {
    console.log(`${this.name} has drowned`);
  }
};

Reptile现在可以创建的对象实例:

croc.__proto__.doesItDrown = function() {
  console.log(`the croc never drowns`);
};

croc.doesItDrown(); // the croc never drowns
alligator.doesItDrown(); // the croc never drowns

prototype对的Reptile,现在目标是继承的基础上,doesItDrown方法是既可以访问alligatorcroc因为prototypeReptile有这个方法。该prototype属性在其所有实例之间共享,并且可以通过__proto__特定实例的属性进行访问。

现在,由于存在方法槽,并且prototype在所有实例之间共享一个公共实例属性,因此可能会出现一些非常巧妙的技巧,这对C ++人士来说很奇怪:

croc.__proto__.doesItDrown = function() {
  console.log(`the croc never drowns`);
};

croc.doesItDrown(); // the croc never drowns
alligator.doesItDrown(); // the croc never drowns

更改一个实例的prototype属性或方法,该对象的所有实例都会受到影响。这意味着我们也可以删除东西。厌倦了溺水的鳄鱼可能会这样做:

delete croc.__proto__.doesItDrown
alligator.doesItDrown();

//TypeError: alligator.doesItDrown
// is not a function

现在没有人去游泳。

这只是一个愚蠢的示例,它展示了prototypeJavaScript对对象系统的根本意义,以及它对来自其他面向对象语言的人们的影响如何。

使用ES6语法,已为JavaScript提供了创建类的功能。

但是,真正的类的概念在JavaScript中不存在,但可以通过它进行仿真,prototype并且类语法只是围绕它的语法糖。因此,了解此行为对于实现ES6类的便利性和局限性很重要。

使用新class语法,Reptile将被定义为:

class Reptile {
  constructor (name, canItSwim) {
    this.name = name;
    this.canItSwim = canItSwim;
  }

  doesItDrown () {
   if(this.canItSwim) 
    console.log(`${this.name} can swim`);
   else
    console.log(`${this.name} has drowned`);
  }
}

let alligator = new Reptile("alligator", true);
alligator.doesItDrown(); //alligator can swim

这并不意味着它不会为prototype用户带来任何新鲜事物,使用ES6类可以避免一些陷阱,例如使new关键字对于创建实例是强制性的。

let croc = Reptile("croc", false);
//TypeError: Class constructor Reptile cannot be invoked without 'new'

这实际上是一件好事,因为它可以防止在使用对象属性和方法(通常是全局范围或窗口对象)时访问错误的上下文。

结论

尽管JavaScript现在确实确实缺少真正的私有成员之类的功能。它使通过类语法创建对象成为可能,而不是使原型与来自其他OO语言(如C ++ / Java)的类非常相似。


PS。TC39提出了在JavaScript类中创建真正的私有成员的建议,您可以在此处关注并提出您的意见。如果它要包含在下一个修订版中,那么我们将有类似以下内容:

class Foo {
  #a; #b; // # indicates private members here
  #sum = function() { return #a + #b; };
}

// personally this format reminds me of $variable in PHP.
// I'm not sure if that's a good thing

其他:

一些关于js原型链的讨论

https://stackoverflow.com/questions/816071/prototype-based-vs-class-based-inheritance

https://medium.com/%40parsyval/javascript-prototype-vs-class-a7015d5473b

https://juejin.im/post/5db0fec4518825648c3a8770

关于 Kendo UI 开发教程

https://www.w3cschool.cn/kendouidevelopmenttutorial/62s81jv1.html

https://github.com/kendo-labs/bower-kendo-ui

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

举报
请填写举报理由
0/200