优雅的类写法

前言

虽然现在已经是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.**方式,还是私有变量的方式,都是独占的。

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

三、代码规范

  • 类的命名规范,业界有不成文的规定,就是首字母大写。
  • 原型上的私有方法,默认以下划线开始。这种只是团队合作方面有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://www.cnblogs.com/walls/p/9339300.html

时间: 2024-08-09 03:17:37

优雅的类写法的相关文章

优雅的css写法

一.利用好代码折叠 css也可以进行优雅的代码折叠而且会比html更好看 折叠后的效果: 这样就可以很舒服的把它折叠起来. 二.向Twitter Bootstrap学习 1. 学习的第一点就是用class,去减少id.当然这是一个很基本的知识. 2. 学习的第二点是命名的词汇. 如group.control.banner.list.item,title.panel.content.container这些表结构和关系的词汇: 还有一些形容词danger.primary.lg.xs.info等等:

如何学好面向对象?类写法的困惑

使用类中方法的两种方式,哪一种会更好一点儿呢? 方法一: class demo {     public $a;     public $b;     public function func1(){         if ($a) {             return true;         } else {             return false;         }     }     public function func2(){         echo $b;  

python-进阶-优雅的python写法

Python 这门语言最大的优点之一就是语法简洁,好的代码就像伪代码一样,干净.整洁.一目了然.但有时候我们写代码,特别是 Python 初学者,往往还是按照其它语言的思维习惯来写,那样的写法不仅运行速度慢,代码读起来也费尽,给人一种拖泥带水的感觉,过段时间连自己也读不懂. 要写出 Pythonic(优雅的.地道的.整洁的)代码,还要平时多观察那些大牛代码,Github 上有很多非常优秀的源代码值得阅读,比如:requests.flask.tornado,笔者列举一些常见的 Pythonic 写

C#常用的正则工具类写法

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Collections; namespace ConsoleApplication1 { /// <summary> /// 字符串正则匹配帮助类 /// </summary> public static cla

修改优先级(类写法)

定义类: unit UUpdateYouXianJi; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Data.DB, Data.Win.ADODB, Vcl.ExtCtrls, Vcl.DBCtrls, Vcl.Gr

[PHP]OOP两类写法的性能对比

在PHP的OOP中我们有常见两种方法调用,对象调用和静态调用. 下面是一个简单的测试来比较它们的细微差异. /** * 对象初始化 -> 调用:objectCall.php * * 测试调用50W次. * * @farwish */ class Test { public $a; public function __construct($a) { $this->a = $a; } public function ab() { return $this->a; } } $obj = new

面向对象【day07】:类的属性-继承-经典类

本节内容 类的公有属性 析构函数 类的继承 新式类和经典类 一.类的公有属性 一.概述 前面我们讲了类的私有属性,现在我们来说说类的公有属性,这边很容易被人弄混淆,有人觉的,在__init__()构造方法中,除了私有属性,其他的都是公有属性了,其实这是一个错误的结论,并不是定义在__init__()初始化方法中的属性是公有属性(除私有属性),那什么是公有属性呢?揭起了大家的好奇心. 定义:指的是所属这个类的所有对象,都可以访问的属性,叫做公有属性. 二.公有属性 2.1 定义 说明:在类中直接定

CSS中伪类及伪元素用法详解

原文:CSS中伪类及伪元素用法详解 伪类的分类及作用: 注:该表引自W3School教程 伪元素的分类及作用: 接下来让博主通过一些生动的实例(之前的作业或小作品)来说明几种常用伪类的用法和效果,其他的读者可以自己尝试: :active  大致效果为用鼠标点击时,元素增加特效,鼠标松开时,特效消失.多用在按钮的点击上. 写法: 这里id为box的是一div块,在css中首先设置了他的基本样式,下面为加入:active伪类后需要修改的样式. 未点击时: 点击之后: :active.:hover.:

Python学习之旅—面向对象进阶知识:类的命名空间,类的组合与继承

前言 上篇博客笔者带领大家初步梳理了Python面向对象的基础知识,本篇博客将专注于解决三个知识点:类的命名空间,类的组合以及面向对象的三大特性之一继承,一起跟随笔者老看看今天的内容吧. 1.类的命名空间 在上一篇博客中,我们提到过对象可以动态添加属性,一起来回忆下昨天的知识点,看如下的代码: class A: pass a = A() a.name = 'alex' print(a.name) 这里我们手动为a对象添加了一个属性name,然后直接打印可以得到a对象的名称.通过这个例子,我们可以