JavaScript 中并没有真正的类,但JavaScript 中有 构造函数 new 运算符。

- 任何JavaScript 函数都可以用做构造函数,

- 构造函数必须使用 new 运算符来创建新的实例。

一、模拟构造函数

大部分语言定义为:construct , 为了区别我们将其命名为:init

// 首先,我们需要一个可以生产类的工厂
var Class = function(){
var klass = function(){
// 执行构造函数,这里的 this 实际上指向了“类”的实例化对象,也就是下文的_person
this.init.apply(this, arguments);
};
klass.prototype.init = function(){};
return klass;
}; // 第一步:生产类
var Person = new Class(); // 第二步:定义类的构造函数init
Person.prototype.init = function(){
// 基于Person 的实例做初始化
alert("我是构造函数,我被自动执行了");
}; // 第三步:实例化对象
var _person = new Person();

 

二、给“类”库添加方法

在JavaScript 中,在构造函数中给类添加函数和给对象添加属性是一模一样的,区别是 静态属性(方法) 和 实例属性 (方法)

静态属性(方法):

// 直接给类添加静态方法
Person.find = function(id){ /* ... */ };
// 这样我们可以直接调用它们
var person = Person.find(1);

实例属性(方法):

var Person = new Class;
// 在原型中定义函数
Person.prototype.save = function(){ /* ... */ };
// 这样就可以在实例中调用它们
var person = new Person;
person.save();

可以看到,要想给构造函数添加实例函数,则需要用到构造函数的prototype,一种常用的模式是给类的prototype 起一个别名fn,写起来也更简单:

Person.fn = Person.prototype;
Person.fn.run = function(){ /*...*/ };

实际上这种模式在jQuery 的插件开发中是很常见的,将函数添加至jQuery.fn 中也就相当于添加至jQuery 的原型中。

但在我看来这种语法有些绕,不切实际且不够简洁,很难一眼就分辨出类的静态属性和实例的属性。因此我们采用另外一种不同的方法来给类添加属性,这里用到了两个函数
extend() 和include() :

var Class = function () {
var klass = function () {
this.init.apply(this, arguments);
}; klass.prototype.init = function () {}; // 定义 prototype 的别名
klass.fn = klass.prototype; // 给类添加静态属性(方法)
klass.extend = function (obj,cb) {for (var o in obj) {
klass[o] = obj[o];
} cb && cb();
}; // 给类添加实例属性(方法)
klass.include = function (obj,cb) {for (var o in obj) {
   klass.fn[o] = obj[o];
}
cb && cb();
}; return klass;
};

这段代码是“类”库的增强版,我们使用extend() 函数来生成一个类,这个函数的参数是一个对象。通过迭代将对象的属性直接复制到类上:

var Person = new Class();
Person.extend({
find: function(id) { alert("我是用户" + id) },
exists: function(id) { alert("用户" + id + "存在") }
});

这种写法之美在于它已经可以支持模块了。模块是可重用的代码段,用这种方法可以实现各种继承,用来在类之间共享通用的属性。比如ORM模块

// 共享的函数
var ORMModule = {
inster:function(){/* 增 */},
del:function(){/* 删 */},
save:function(){/* 改 */},
select:function(){/* 查 */}
};
var Person = new Class;
var Asset = new Class;
Person.include(ORMModule);
Asset.include(ORMModule);

基于原型的类继承

创建一个父类

var Animal = function(){};
Animal.prototype.breath = function(){
console.log('breath');
};

创建一个子类

var Dog = function(){};

// 子类自己的个性方法,和本例无关,只是为了演示
Dog.prototype.wag = function(){
console.log('wag tail');
};

将父类的实例赋值给子类的原型

Dog.prototype = new Animal;

至此,我们就轻松实现了继承,我们来检查一下继承是否生效了

var dog = new Dog();
dog.breath(); // breath

js - 类模拟的更多相关文章

  1. WEB开发:如何用js来模拟服务器的ajax响应,不依赖服务器来编写前端代码

    一.问题的提出 目前web前端开发,主流的思路是: 1)编写静态的html文件(不使用模板技术,与服务器无关) 2)页面通过ajax与服务器交互,进行数据的传输,数据格式为json格式 这里存在一个问 ...

  2. 自己手写的自动完成js类

    在web开发中,为了提高用户体验,会经常用到输入框的自动完成功能,不仅帮助用户进行快速输入,最重要的是帮助那些“记不全要输入什么”的用户进行选择.这个功能有很多插件已经实现了,为了适应项目的特殊需求, ...

  3. 【前端】js代码模拟用户键盘鼠标输入

    js代码模拟用户键盘鼠标输入 原生js var event = new Event('mousewheel'); event.wheelDelta = 360 document.dispatchEve ...

  4. JS类的封装及实现代码

    js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 我们来封装一个简的Shape类. 1. ...

  5. 几种常用的JS类定义方法

    几种常用的JS类定义方法   // 方法1 对象直接量var obj1 = {    v1 : "",    get_v1 : function() {        return ...

  6. js类(继承)(二)

    1. 定义js类 js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 我们来封装一个简的Sh ...

  7. Java基础知识强化之IO流笔记55:IO流练习之 自定义类模拟LineNumberReader的获取行号功能案例

    1. 自定义类模拟LineNumberReader的获取行号功能案例 2. 代码实现: (1)MyBufferedReader.java: package cn.itcast_08; import j ...

  8. JS类继承常用方式发展史

    JS类继承常用方式发展史 涉及知识点 构造函数方式继承 1-继承单个对象 1.1 多步走初始版 1.2 多步走优化版 1.3 Object.create()方式 2-继承多个对象 2.1 遍历 Obj ...

  9. 两种简单实现菜单高亮显示的JS类(转载)

    两种简单实现菜单高亮显示的JS类   近期在写一个博客管理后台的前端,涉及在同一页面两种高亮显示当前菜单的需求.记得当年写静态页时,为了实现高亮都是在每个页面加不同的样式,呵.高亮显示我觉得对于web ...

随机推荐

  1. 最小生成树 (Minimum Spanning Tree,MST) --- Prim算法

    本文链接:http://www.cnblogs.com/Ash-ly/p/5409904.html 普瑞姆(Prim)算法: 假设N = (V, {E})是连通网,TE是N上最小生成树边的集合,U是是 ...

  2. hdu6138(后缀数组)

    hdu6138 题意 给出若干个字符串,每次查询两个字符串,求两个字符串的公共子串且在给出的某一个字符串中作为前缀的最大长度. 分析 求公共子串:后缀数组 判断前缀:字典树 求完后缀数组,遍历下 \( ...

  3. LCA+差分【p4427】[BJOI2018]求和

    Description master 对树上的求和非常感兴趣.他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的\(k\) 次方和,而且每次的\(k\) 可能是不同的.此处节点深度的 ...

  4. [BZOJ 1499] 瑰丽华尔兹

    Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1499 Solution : 能立即发现这是和动态规划相关的题目 令f[t][i][j]表 ...

  5. 【DFS】bzoj2079 [Poi2010]Guilds

    对一棵树黑白染色一定符合题意. 图一定有生成树. 因此,仅有一个孤立节点的联通块不合题意. DFS. #include<cstdio> using namespace std; int n ...

  6. 【二分】bzoj2083 [Poi2010]Intelligence test

    v[x]记录了x值的出现位置序列. 对每个b中的元素,每次在v[b[i]]中二分. 因此要记录上一次二分到了a数组的哪个位置. #include<cstdio> #include<v ...

  7. 【斜率优化】BZOJ1096-[ZJOI2007]仓库建设

    [题目大意] 有n个工厂编号分别为1-n,第i个仓库库存量为p[i],距离第1个仓库的距离为x[i](x[1]=0).在每一个工厂建立一个仓库费用为c[i],没有建立仓库的工厂只能往编号大于它的仓库运 ...

  8. python基础--常用模块与面向对象基础

    1常用模块 1.1 xml xml是实现不同语言或程序之间进行数据交换的协议 xml的格式如下: <?xml version="1.0"?> <data> ...

  9. SVN 文件删除及恢复

    SVN 文件删除及恢复 在TortoiseSVN管理的项目中删除文件的方法:   1. 在客户端按delete删除(OS中删除,不通过SVN)           ● 未提交之前一旦Update则被删 ...

  10. 线程协作-CountDownLatch

    CountDownLatch允许一个或多个线程等待其他线程完成操作.