文档章节

优雅的写出类

p
 peakedness丶
发布于 10/20 20:31
字数 1176
阅读 9
收藏 1

前言

虽然现在已经是ES6的时代,但是,还是有必要了解下ES5是怎么写一个类的。 本文详述JavaScript面向对象编程中的类写法,并分步骤讲述如何写出优雅的类。

一、例子

例子为一个轻提示组件Toast。 需要实现的功能:

  • on方法,显示提示
  • off方法,隐藏提示
  • init方法,初始化提示语
function Toast(option){
  this.prompt = '';
  this.elem = null;
  this.init(option);
}

Toast.prototype = {
  // 构造器
  constructor: Toast,
  // 初始化方法
  init: function(option){
    this.prompt = option.prompt || '';
    this.render();
    this.bindEvent();
  },
  // 显示
  show: function(){
    this.changeStyle(this.elem, 'display', 'block');
  },
  // 隐藏
  hide: function(){
    this.changeStyle(this.elem, 'display', 'none');
  },
  // 画出dom
  render: function(){
    var html = '';
    this.elem = document.createElement('div');
    this.changeStyle(this.elem, 'display', 'none');

    html += '<a class="J-close" href="javascript:;">x</a>'
    html += '<p>'+ this.prompt +'</p>';

    this.elem.innerHTML = html;

    return document.body.appendChild(this.elem);
  },
  // 绑定事件
  bindEvent: function(){
    var self = this;

    this.addEvent(this.elem, 'click', function(e){
      if(e.target.className.indexOf('J-close') != -1){
        console.log('close Toast!');
        self.hide();
      }
    });
  },
  // 添加事件方法
  addEvent: function(node, name, fn){
    var self = this;

    node.addEventListener(name, function(){
      fn.apply(self, Array.prototype.slice.call(arguments));
    }, false);
  },
  // 改变样式
  changeStyle: function(node, key, value){
      node.style[key] = value;
  }
};

var T = new Toast({prompt:'I\'m Toast!'});
T.show();

二、类的构成

JavaScript的类,是用函数对象来实现。 类的实例化形式如下:

var T = new Toast();

其中的重点,就是Function的编写。

类分为两部分:constructor+prototype。也即构造器+原型

2.1 构造器

构造器从直观上来理解,就是写在函数内部的代码。 从Toast例子上看,构造器就是以下部分:

function Toast(option){
  this.prompt = '';
  this.elem = null;
  this.init(option);
}

这里的this,指向的是实例化的类。 每次通过new Toast()的方式进行实例化,构造器都会执行一遍

2.2 原型

原型上的方法和变量的声明,都是通过Toast.prototype.*的方式。

那么在原型上普通的写法如下:

Toast.prototype.hide = function(){/*code*/}
Toast.prototype.myValue = 1;

但是,该写法不好的地方:就是每次都要写前半部分Toast.prorotype,略显累赘。 在代码压缩优化方面也不友好,无法做到最佳的压缩。 改进的方式如下:

Toast.prorotype = {
  constructor: Toast,
  hide: function(){/*code*/},
  myValue: 1 
}

这里的优化,是把原型指向一个新的空对象{}

带来的好处,就是可以用{key:value}的方式写原型上的方法和变量。

但是,这种方式会改变原型上构造器prototype.constructor的指向。

如果不重新显式声明constructor的指向,Toast.constructor.prototype.constructor的会隐式被指向Object。而正确的指向,应该是Toast

虽然通过new实例化没有出现异常,但是在类继承方面,constructor的指向异常,会产生不正确的继承判断结果。这是我们不希望看到的。

所以,需要修正constructor

2.3 构造器和原型的不同

原型上的方法和变量,是该类所有实例化对象共享的。也就是说,只有一份。

而构造器内的代码块,则是每个实例化对象单独占有。不管是否用this.方式,还是私有变量的方式,都是独占的。

所以,在写一个类的时候,需要考虑该新增属性是共享的,还是独占的。以此,决定在构造器还是原型上进行声明。

前端全栈交学习流圈:866109386。 欢迎大家进入交流吹水。

三、代码规范

  • 类的命名规范,业界有不成文的规定,就是首字母大写。
  • 原型上的私有方法,默认以下划线开始。这种只是团队合作方面有review代码的好处,实际上还是暴露出来的方法。

四、使实例化与new无关

类的实例化,一个强制要求的行为,就是需要使用new操作符。如果不使用new操作符,那么构造器内的this指向,将不是当前的实例化对象。 优化的方式,就是使用instanceof做一层防护。

function Toast(option){
  if(!(this instanceof Toast)){
    return new Toast(option);
  }

  this.prompt = '';
  this.elem = null;
  this.init(option);
}

从上述代码可以看出,使用这个技巧,可以防止团队一些大头虾出现使用错误实例化方式,导致代码污染的问题。 这种忍者技巧很酷,但从另一方面考虑,还是希望使用者可以用正确的方式去实例化类。

所以,改成以下这种防护方式

function Toast(option){
  if(!(this instanceof Toast)){
    throw new Error('Toast instantiation error');
  }

  this.prompt = '';
  this.elem = null;
  this.init(option);
}

这样,把锅甩回去,岂不是更妙

出处:https://blog.csdn.net/q3254421/article/details/83216312

© 著作权归作者所有

共有 人打赏支持
p
粉丝 19
博文 63
码字总数 65534
作品 0
长沙
私信 提问
关于php语言

1 首先,php语言是一门动态语言,弱类型,解释执行; 2 其次,说说php的语法,他的语法跟c++的类似,与其他脚本语言ruby/python有区别,区别只不过是语法糖多或少的问题; 3 然后,说说编程思想...

shigebeyond
2014/07/05
0
0
TypeScript 数据模型层编程的最佳实践

虽然 TypeScript 主要用于客户端,而数据模型的设计主要是服务端来做的。 但是要写出优雅的代码,也还是有不少讲究的。 让我们从一个简单的我的文章列表 api 返回的数据开始,返回的文章列表...

banxi
07/02
0
0
PHP "延迟静态绑定" 功能,static

从这个名字的定义提取出两个关键点,第一点静态,也就是说这个功能只适用于静态属性或静态方法。 第二点延迟绑定,这个根据下面代码就可以很好的理解 我在printName函数里面使用了self关键字...

nsns
09/25
0
0
C#7.0中的解构功能---Deconstruct

解构元组   C#7.0新增了诸多功能,其中有一项是新元组(ValueTuple),它允许我们可以返回多个值,并且配合解构能更加方便的进行工作,如下面例子 static void Main(string[] args){(var nam...

莫问今朝乄
08/20
0
0
Ruby 学习路径

曾几何时,在初学完编程之后,好长一段时间停留在初级程序员阶段,不知道怎么再提高。那时候想着如果有人分享个某个语言的学习路径的话就太好了。 现在,我给大家分享一些我经过各种弯路以后...

rocLv
2017/12/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

day150-2018-11-17-英语流利阅读-待学习

歪果仁也疯狂:海外版抖音的征途 毛西 2018-11-17 1.今日导读 海外版抖音 TikTok 于 2017 年 5 月上线海外,至今覆盖全球 150 多个国家和地区,月活跃用户数已突破 5 亿。然而,“出海”的抖...

飞鱼说编程
今天
5
0
分布式学习最佳实践:从分布式系统的特征开始(附思维导图)

什么是分布式系统 回到顶部   分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机无法...

dragon_tech
今天
4
0
TOKEN设计

TOKEN设计 Api_Token 首先需要知道API是什么? API(Application Programming Interface)即应用程序接口。你可以认为 API 是一个软件组件或是一个 Web 服务与外界进行的交互的接口。而我们在...

DrChenXX
今天
3
0
浅谈“李氏代换”——从纪念金庸和斯坦李说起

李氏代换(LSP)简介 李氏代换是软件设计的一个原则,又名依赖倒转原则或依赖倒置原则,其衍生原则有接口分离原则等。该原则由Barbara Liskov于1988年提出。 该原则指出,程序中高级别的元素...

SamYjy
今天
35
0
JavaScript实现在线websocket WSS测试工具 -toolfk程序员工具网

本文要推荐的[ToolFk]是一款程序员经常使用的线上免费测试工具箱,ToolFk 特色是专注于程序员日常的开发工具,不用安装任何软件,只要把内容贴上按一个执行按钮,就能获取到想要的内容结果。T...

toolfk
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部