js面向对象设计之class类
class 相对 function 是后出来的,既然 class 出来了,显然是为了解决 function 在处理面向对象设计中的缺陷而来。
下面通过对比,来看看 class 作为 ES6 中的重大升级之一的优势在哪里:
为了更好的对比,请参见我的另外一篇博文: js面向对象设计之 function 类。 1、class 写法更加简洁、含义更加明确、代码结构更加清晰。
2、class 尽管也是函数,却无法直接调用(不存在防御性代码了)。
3、class 不存在变量提升。
4、class 为污染 window 等全局变量(这点很赞啊)。
5、class 函数体中的代码始终以严格模式执行(新手写的代码可靠性也必须上来了) /* ReferenceError: Class01 is not defined */
try { var ins01 = new Class01(); } catch ( e ) { console.error( e ); }
class Class01 { }
console.log( typeof Class01 ); /* function */
/* Class constructor Class01 cannot be invoked without 'new' */
try { Class01() } catch ( e ) { console.error( e ); }
console.log( window.Class01 ); /* undefined */
6、可直接使用 set 和 get 函数。这比 function 要好用多了。
据我所知,vue 中的数据绑定是通过 set 和 get 来实现,而这里 class 可以使用便捷的如同普通的函数的写法。
function 中则需要通过 Object.defineProperty 的方式来设置 set 和 get,繁琐且代码可读性差。 class Class01{
constructor() { }
get name(){
console.log( 'getter' );
return this._name;
}
set name( v ){
this._name = v;
console.log( 'setter' );
return this;
}
}
var ins01 = new Class01();
ins01.name; /* getter */
ins01.name = ; /* setter */
7、class 内部方法中若涉及到 this,则一定要注意。class 中的 this 永远都不会指向 window。
熟悉 function 的应该知道,function 类的实例方法,可能指向 window(在某些情况下,具体读者可自行百度,也可阅读下述例子推敲)。
而 class 则在 this 可能指向 window 的情况下,将 this 指向 undefined。如下:
class Class01 {
constructor() {
this.a = 'a';
}
geta(){
return this.a;
}
}
let ins01 = new Class01();
console.log( ins01.geta() ); /* a */
let obj = {};
obj.a = 'objA';
obj.geta = ins01.geta;
console.log( obj.geta() ); /* 'objA' */
window.a = 'windowA';
window.geta = ins01.geta;
/* Cannot read property 'a' of undefined */
/* 若是 function 类此处会返回 'windowA' */
try { geta() } catch ( e ) { console.error( e ); }
8、class 可以从 javascript 中著名的几大类中进行继承:Array、number、string....,显然 function 是做不到的。
下面给一个简单的示例:
class Class01 extends Array { }
let ins01 = new Class01( , , 3 ); /* [1,2,3] */
let arr = ins01.shift(); /* [2,3] */
arr instanceof Class01; /* false */
ins01 instanceof Class01; /* true */ 小tips:在 mozilla 的开发者指南中看到一种比较高端的东西(关于从原生类继承肯定还有话题,会继续学习):
static get [Symbol.species]() { return Array; }
参见 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes 9、class 中有一个对象(姑且这么称呼,关于 super 显然还必须要有话题)super,这个对象可以取到父类的方法、构造函数等。
这显然是 function 无法比拟的。在 class 的构造函数中,必须调用 super(),否则该子类就毫无用处。当然静态方法还是可以用用。
下面有一个例子,可以重写父类的方法,扩充父类方法的职责(注意是扩充而不是重写,当然也可以选择重写)。
这一点相当的赞啊,有时候我们并不需要改写父类的某个方法,我们可能会因为项目的需求而扩充父类接口的功能。
class Class01 {
constructor( name ){
this.name = name;
}
geta(){
console.log( this.name + ' 父类方法.' );
}
}
class Class02 extends Class01 {
geta(){
super.geta();
console.log( this.name + ' 子类方法.' );
}
}
var l = new Class02( 'Class02' );
l.geta(); 10、class 中不存在实例方法,class 中定义所有方法都是原型方法。这些方法也都是不可枚举的,使用 for in 这种方式无法遍历到它们。
11、class 不能使用 return 来返回一个实例(等等,我还没有试验过,不好意思,我会马上试验一下)。
20180101编辑验证,class 的 constructor 可以使用 return,因此 class 与 function 一样可以返回任意的内容。
若不写 return 语句,或返回是数值、字符串等非引用类型的值,则 constructor 任然会返回 this(实例)。return [] 或 return {} 都会使得 new 关键字并不会返回 class 的实例 说了这么多的不同点,再来说说 class 和 function 的相同之处: 1、静态方法 在这点上,两者还是有相似之处的。
尽管相似,显然 class 要更加优雅,可读性也更强,class 使用 static 关键词指定静态方法。
并且class 可以在函数体内定义静态函数,而 function 不能,这无疑也让 function 写出来的代码更加的复杂。 class Class01{
static geta(){
console.log( '01的静态方法' );
}
}
function Class02 () { }
Class02.geta = function () { console.log( '02的静态方法' ); }
Class01.geta();
Class02.geta(); 2、私有属性和方法
两者都必须采用闭包的方式才能实现。下面给出 class 的私有属性和方法。 var Class02 = ( function () {
let pVal ;
function sayHello(){
console.log( this ); /* this 指向 window */
console.log( '欢迎访问nDos的博客' );
}
return class Class01{
constructor( v = '初始值' ){
pVal = v;
}
get val(){
sayHello();
return pVal;
}
set val( v ){
pVal = v;
}
};
} )();
let ins01 = new Class02();
console.log( ins01.val );
ins01.val = 'hello';
console.log( ins01.val );
ins01 instanceof Class02; /* true */
ins01.constructor.name; /* "Class01" */ 小tips:上面的代码显示 ins01 是 Class02 的实例,但 ins01 的构造函数 name 属性却是 Class01。
显然这在项目中不可行,会给类的使用者造成困惑。下例可解决这个问题:
var Class01 = ( function () {
return class Class01 { };
} )();
let ins01 = new Class01();
ins01 instanceof Class01; /* true */
ins01.constructor.name; /* "Class01" */
3、class 和 function 都有初始化的过程,也就是给实例 this 进行包装处理的过程。二者尽管这个过程都存在,但还是有些区别,
class 只能在 constructor 中初始化,如果涉及继承,还必须调用 super();function 的整个函数体都在执行初始化。 总结:
1、class 作为前端的面向对象设计之关键词,使得前端大型项目的开发变得容易:类的管理更加清晰,功能更加强大。
2、显然与 class 关键字一起出现的关键字 extends 是配套的。使得继承关系更加清晰。
继承再也不用写一堆的prototype指着这个指着那个,项目代码结构更加明确。
3、当然,关于 class 该博文并未挖的很深,留待下文。
js面向对象设计之class类的更多相关文章
- js面向对象设计之function类
本文仅探讨如何合理的使用 function 在 javascript中实现一个面向对象设计的类.总所周知,javascript 并不能实现一个真正意义上的类,比如 protect 比如 函数重载.下面 ...
- js面向对象设计之class继承
EcmaScript 2015 (又称ES6)通过一些新的关键字,使类成为了JS中一个新的一等公民.但是目前为止,这些关于类的新关键字仅仅是建立在旧的原型系统上的语法糖,所以它们并没有带来任何的新特性 ...
- JS面向对象设计-理解对象
不同于其他面向对象语言(OO,Object-Oriented),JS的ECMAScript没有类的概念, 它把对象定义为"无序属性(基本值.对象.函数)的集合",类似于散列表. 每 ...
- js面向对象设计之class中一些坑和技巧
this的指向 super 类工厂,类中定义方法名时,可以使用字符串,这就可以创建工厂函数(类似模板类) Generator 函数 静态属性和私有属性.私有方法 new.target
- JS面向对象设计-创建对象
Object构造函数和对象字面量都可以用来创建单个对象,但是在创建多个对象时,会产生大量重复代码. 1.工厂模式 工厂模式抽象了创建具体对象的过程.由于ECMAScript无法创建类,我们用函数来封装 ...
- 【JavaScript】 JS面向对象的模式与实践 (重点整治原型这个熊孩子 (/= _ =)/~┴┴ )
参考书籍 <JavaScript高级语言程序设计>—— Nicholas C.Zakas <你不知道的JavaScript> —— KYLE SIMPSON 在JS的面向 ...
- js面向对象编程 ---- 系列教程
原 js面向对象编程:数据的缓存 原 js面向对象编程:如何检测对象类型 原 js面向对象编程:if中可以使用那些作为判断条件呢? 原 js面向对象编程:this到底代表什么?第二篇 原 js面向对象 ...
- python之面向对象设计、编程
面向对象 一.编程三个范式 1.面向过程编程 2.函数式编程 数学层面的函数 python中的函数编程 3.面向对象编程 二.面向对象设计 1.类:把一类事物共同的特征和共同的动作整合在一起就是类: ...
- UML类图与面向对象设计原则
1. 引言 从大一开始学习编程,到如今也已经有两年了.从最初学习的Html,Js,JaveSe,再到JavaEE,Android,自己也能写一些玩具.学习过程中也无意识的了解了一些所谓的设计模 ...
随机推荐
- 如何在for循环中使用多线程
import java.util.concurrent.Executor;import java.util.concurrent.Executors; public class Test {priva ...
- 使用泛型SwingWorker与EDT事件分发线程保持通讯
为什么要使用SwingWorker 在swing开发中,如果一个应用程序,执行一些任务,需要大量的时间来完成,比如下载一个大文件或执行一个复杂的数据库查询. 我们假设这些任务是由用户使用一个按钮触发的 ...
- commons-logging.jar 和 log4j.jar 的关系
在用springmvc开发项目的时候,在日志管理这一块,我们一般用的都是log4j进行日志管理,但是我们在导入spring相关的jar的时候,都会看到commons-logging.jar包,为什么我 ...
- Elasticsearch四种常见的相关度分数优化方法
**1.boost方式 ** 简单粗暴,最常用. 需求:查询出title和content中包含java spark的document 方式1: GET /forum/article/_search { ...
- Spring Boot 项目发布到 Tomcat 服务器
第 1 步:将这个 Spring Boot 项目的打包方式设置为 war.<packaging>war</packaging> SpringBoot 默认有内嵌的 tomcat ...
- Android4.0 Launcher拖拽原理分析
在Android4.0源码自带的Launcher中,拖拽是由DragController进行控制的. 1) 先来看看类之间的继承关系 2)再来看看Launcher拖拽流程的时序图 1.基本流程: ...
- javac的泛型
?:在实例化对象的时候,不确定泛型参数的具体类型时,可以使用通配符进行对象定义. (1)?表示通配符,通配符 与 T 的区别 T:作用于模板上,用于将数据类型进行参数化,不能用于实例化对象. publ ...
- fastText 安装
Windows: https://www.lfd.uci.edu/~gohlke/pythonlibs/#fasttext 下载需要的版本 然后:pip install 文件名
- Web服务(Apache、Nginx、Tomcat、Jetty)与应用(LAMP、CMS-WordPress&Ghost、Jenkins、Gitlab)
Web服务和应用是目前信息技术领域的热门技术.如何使用Docker来运行常见的Web服务器(包括Apache.Nginx.Tomcat等),以及一些常用应用(LAMP.CMS等).包括具体的镜像构建方 ...
- Rails 增加一个模型(model)
之前我们已经看到用脚手架运行的model程序.现在是时候第二个model了. 第二个model用来处理post的评论. 7.1 新建一个模型 Rails模型使用一个单一的的名称,其相应的数据库表使 ...