javascript 面向对象设计之 Function 普通类
var test = "Class01";
function Class01(privateValue, publicValue) {
var _this = this;
if (this.constructor.name !== 'Class01') { throw new Error('类只能被实例化'); }
/*统计实例化次数的自执行函数*/
(function newClass() {
Class01.count++; /*统计实例化的次数*/
Class01.intances.push(_this); /*保存每个实例的引用*/
console.log(Class01.count);
})();
/*私有变量和私有方法*/
function privateMethod() { console.log('private method was called by publicMethod') } //
var privateVal = privateValue;
/*私有变量储存接口*/
this.get = function () { return privateVal; };
this.set = function (v) { privateVal = v; return this; };
/*实例属性和实例方法(一般并不会创建实例方法,如果一定要定义实例方法,实例化之后自行添加)*/
this.public = publicValue;
this.publicMethod = function () {
console.log('public method and then call private method');
privateMethod(); /*内部使用私有方法*/
return this;
};
/*实例方法可以使用类的静态属性和方法*/
this.callClassStaticMethod = function () {
console.log(Class01.staticValue);
Class01.staticMethod();
};
}
/* 原型属性和方法
* 1、类被实例化次数和保存引用的数组也可以放在原型中
* 2、每个实例都拥有其他实例的引用和实例化次数
*/
Class01.prototype.proValue = 'this is Class01 prototype value';
Class01.prototype.proMethod = function () {
console.log('this is Class01 prototype method');
};
Class01.prototype.proArray = [, , , , ];
Class01.prototype.proObject = { a:'a' };
/* 静态属性和静态方法
* 静态属性是否可用于储存该类被实例化的次数,通过在类中加入一个自执行函数即可。
* 也可以在每次实例化的时候执行某种操作
* 1、比如当实例化的数量超过某个值的时候,抛出错误,告诉程序内存占用过高。
* 2、可以在类的静态属性中,保存每个实例的引用(肯定造成内存泄漏)。
*/
Class01.staticValue = 'this is class static value';
Class01.staticMethod = function () { console.log('this is class static method') };
Class01.count = ;
Class01.intances = [];
/* 测试 Class01 */
if (test === "Class01") {
var instance01 = new Class01('private value1', 'public value1');
var instance02 = new Class01('private value2', 'public value2');
console.log(Class01.intances);
console.log('实例私有属性');
console.log(instance01.get());
console.log(instance01.set('change private value1').get());
console.log(instance02.get());
console.log(instance02.set('change private value2').get());
console.log('实例属性');
console.log(instance01.public);
console.log(instance02.public);
console.log('实例方法');
instance01.publicMethod();
instance02.publicMethod();
console.log(instance01.publicMethod === instance02.publicMethod);
console.log('实例原型属性');
console.log(instance01.proValue);
instance01.proValue = 'instance01 change proto value';
console.log(instance01.proValue);
console.log(instance02.proValue);
/*instance01并没有能够修改原型属性,而是在实例上创建了实例属性*/
try {
/*无法在实例上改变原型上的属性*/
instance01.prototype.proValue = 'class static value changed';
} catch (e) {
console.error(e);
}
try {
/*总之实例不允许使用prototype来使用属性和方法*/
console.log(instance02.prototype.proValue);
} catch (e) {
console.error(e);
}
/*若原型属性是数值/字符串/布尔值,实例是没有手段可以修改。当原型属性是引用时(数值/对象)时,便可以修改从而在所有的实例对象上会反应出来。*/
console.log(instance01.proArray);
instance01.proArray.push();
console.log(instance02.proArray);
console.log('类静态方法');
instance01.callClassStaticMethod();
instance02.callClassStaticMethod();
try {
/*不能在实例上设置 prototype 方法(原因很简单,十几个人做一个项目,每个人都想往实例原型上添加方法,项目则无法完成)*/
instance01.prototype.print = function () {
console.log('prototype');
};
} catch (e) {
console.error(e);
}
try {
/*尽管 Class01 是 function 但是并不能执行*/
Class01();
} catch (e) {
console.error(e);
}
try {
/*显然也不能采用 call 的方式。*/
var instance03 = {};
Class01.call(instance03, 'private value3', 'public value3');
} catch (e) {
console.error(e);
}
/*以下这种方法,能够使用 Class01 进行函数式"实例化",但是原型都消失了。*/
function Class01_t() {
}
Class01_t.prototype.constructor = {name: 'Class01'};
var instance04 = new Class01_t();
Class01.call(instance04, 'private value4', 'public value4');
console.log(instance04);
/* 下面这种方法能够完美模拟 Class01 实例化
* 1、以下例子可以看出,在Class01_t2中,可以添加实例新的属性和方法。
* 下面从继承的角度去看。
* 2、Class01_t2中定义的属性和方法,显然会被 Class01中的覆盖掉。
* 3、在Class01_t2原型上添加方法和属性,显然会覆盖Class01的。从而影响所有的由Class01创建的实例
* 4、无论如何,Class01静态方法和属性都在constructor中
* 目前的主题并不是类的继承,关于function类的实例化和相关知识目前先介绍这么多。
*/
function Class01_t2() {
console.log('Class01_t2 was called');
Class01.call(this, 'private value5', 'public value5');
/* 从此处开始可以劫持Class01的公有属性和方法,无法劫持私有的属性和方法(无法取得其引用,自然无法调用)。
* 使用 Function.prototype.after 的方式可以实现劫持各种方法。
*/
}
Class01_t2.prototype = Class01.prototype;
var instance05 = new Class01_t2();
console.log(instance05);
instance05.constructor.staticMethod();
console.log(instance05.constructor === Class01);
/*构造函数指向 Class01;*/
console.log(instance05.prototype);
/*undefined*/
console.log(instance04.prototype);
/*undefined*/
console.log(instance01.prototype);
/*undefined*/
console.log(Class01_t2.constructor === Class01.constructor);
/*构造函数相等*/
console.log(Class01_t2.__proto__ === Class01.__proto__);
/*true*/
console.log(instance05.__proto__ === instance01.__proto__);
/*true*/
console.log(instance05.constructor.name);
/*Class01*/
/*通过实例的 constructor 可以找到类。可以通过new constructor 从而可以从类实例化。*/
console.log(instance05.__proto__.constructor === Class01);
/*true*/
console.log(instance05.constructor === Class01);
/*true*/
var instance06 = new instance05.constructor('private value6', 'public value6');
console.log(instance06.get());
/* 总结
* 1、只有函数才能被实例化,实例化之后得到的变量是实例并不是函数,或者说是object
* 2、有一种可以不修改 Class01 也可以扩充变量或方法(公有或私有)的方式,上述 Class01_t2
* 对于这种方式,由相当多的内容可以想象:比如是否可以劫持Class01中的公有方法
*/
}
javascript 面向对象设计之 Function 普通类的更多相关文章
- 设计模式学习(二):面向对象设计原则与UML类图
一.UML类图和面向对象设计原则简介 在学习设计模式之前,需要找我一些预备知识,主要包括UML类图和面向对象设计原则. UML类图可用于描述每一个设计模式的结构以及对模式实例进行说明,而模式结构又是设 ...
- js面向对象设计之function类
本文仅探讨如何合理的使用 function 在 javascript中实现一个面向对象设计的类.总所周知,javascript 并不能实现一个真正意义上的类,比如 protect 比如 函数重载.下面 ...
- JavaScript面向对象编程(2)-- 类的定义
最近这一段时间事情太多了,没有时间再继续写,幸好这两天有点小闲,先小写一下JavaScript中面向对象一中推荐的方法.本文承接上一篇JavaScript面向对象编程(1) -- 基础. 上篇说过,J ...
- 分享几个原生javascript面向对象设计小游戏
一.序言 不知大家是不是和我一样,当初都有个梦想.学编程,就是想开发游戏.结果进入大学学习之后,才知道搞的是数据库应用程序开发!在此,本人就分享下业余时间做的几个小游戏吧!本打算想用winform或w ...
- js面向对象设计之class类
class 相对 function 是后出来的,既然 class 出来了,显然是为了解决 function 在处理面向对象设计中的缺陷而来.下面通过对比,来看看 class 作为 ES6 中的重大升级 ...
- day24:面向对象设计与面向对象编程、类和对象
一.三大编程范式: 面向过程: 面向函数: 面向对象: 二.程序的进化论: 1.编程最开始就是无组织无结构,从简单控制流中按步写指令 2.从上述的指令中提取重复的代码块或逻辑,组织到一起(比方说,你定 ...
- JavaScript面向对象编程(二)构造函数和类
new关键字和构造函数 在文章JavaScript面向对象编程(一)原型与继承中讨论啦JavaScript中原型的概念,并且提到了new关键字和构造函数.利用new关键字构造对象的实例代码如下: // ...
- JavaScript 面向对象编程(三)如何写类和子类
在JavaScript面向对象编程(一)原型与继承和JavaScript面向对象编程(二)构造函数和类中,我们分别讨论了JavaScript中面向对象的原型和类的概念.基于这两点理论,本篇文章用一个简 ...
- UML类图与面向对象设计原则
1. 引言 从大一开始学习编程,到如今也已经有两年了.从最初学习的Html,Js,JaveSe,再到JavaEE,Android,自己也能写一些玩具.学习过程中也无意识的了解了一些所谓的设计模 ...
随机推荐
- 在写一点关于MySQL的知识,感觉自己mmd
DBMS(Database Management System)数据库管理系统 包括有DDL(数据定义语言)和DML(数据操纵语言)以及DCL(数据库控制语言) 数据库设计方法: 1.需求分析阶段 ...
- mongoose返回值无法修改
mongoose 查询方法 find 例:db.collections.find(query,function(err,doc) { 如果var res = doc[0] 是{name:'feife ...
- ReentrantLock可重入锁的使用场景
摘要 从使用场景的角度出发来介绍对ReentrantLock的使用,相对来说容易理解一些. 场景1:如果发现该操作已经在执行中则不再执行(有状态执行) a.用在定时任务时,如果任务执行时间可能超过下次 ...
- Verilog中变量位宽注意
Verilog中,变量定义方式可以为:reg[位宽-1:0] 数据名:reg[位宽:1] 数据名.其他变量也类似. 以reg变量cnt为例,当cnt位宽为4时,可定义为reg[3:0] cnt,或者定 ...
- 使用dropwizard(5)--加入swagger
前言 Swagger已经成API service的规范了,本处在dropwizard中简单集成Swagger. Demo source https://github.com/Ryan-Miao/l4d ...
- shell ping一个IP,延时大于5,输出延时大于5s,打印输出
# ping一个IP,延时大于5,输出延时大于5s,打印输出 #!/bin/bash ip=$* echo $ip num=`ping -c 10 ${ip}|grep icmp_seq|awk ' ...
- SpringMVC中遇到页面跳转出现404错误的问题
今天遇到了一个问题: 使用SpringMVC时,出现页面无法跳转的情况(404错误), 出现这个异常的原因在于SpringMVC的配置文件中控制器的配置书写错误: 原代码: <context:c ...
- 超级有用的Vim命令
你是否曾经烦恼,每次编辑vim文件,想要跳到一行结尾,需要按多次右键,每次想找到某个字符的位置,都得用肉眼去观察,每次想跳到文件结尾,都要按多次向下键.现在,你不必担心这些繁杂的过程,因为我们完全可以 ...
- 基于Flink秒级计算时CPU监控图表数据中断问题
基于Flink进行秒级计算时,发现监控图表中CPU有数据中断现象,通过一段时间的跟踪定位,该问题目前已得到有效解决,以下是解决思路: 一.问题现象 以SQL02为例,发现本来10秒一 ...
- Libevent 事件管理和添加事件
/** 我们先来看一下事件的创建*/struct event * event_new(struct event_base *base, evutil_socket_t fd, short even ...