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 = [1, 2, 3, 4, 5];
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 = 0;
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(6);
    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中的公有方法
     */
}

原文地址:https://www.cnblogs.com/ndos/p/8120073.html

时间: 2024-11-07 01:15:06

javascript 面向对象设计之 Function 普通类的相关文章

[JavaScript] JavaScript 面向对象设计 (3) : 多态与界面篇

在前一篇中我们介绍了基础的 JavaScript 继承实践法,透过 Object.prototype 我们可以自由决定对象要继承自哪个对象,也可以扩充对象目前现有的属性和方法 (和 C# 的 Extension Method 有异曲同工之妙),在本篇中,我们要来介绍面向对象的另一个特性:多态 (Polymorphism). 在前一篇中我们介绍了基础的 JavaScript 继承实践法,透过 Object.prototype 我们可以自由决定对象要继承自哪个对象,也可以扩充对象目前现有的属性和方法

js面向对象设计之function类

/*本文并非是介绍JavaScript的原型的原理的文章, **仅仅讨论function作为类来使用时如何近似传统的面向对象设计 **/ /*function作为类的用法 **下面是一个最简单的类 **实例将有自己的属性val和pVal,也有方法printVal和pMethod **/ function Class01( val, pVal ) { this.val = val; /*实例可直接读写的属性*/ var pVal = pVal; /*实例无法直接读写的属性*/ } Class01.

Javascript使用function创建类的两种方法

1.使用function类 //myFunction.js var CMyFunc=function() { //类的公共方法,供外部调用 this.Func1=function() { var i=0; return i; } this.Func2=function() { _privateFunc(); } //类中的私有方法,供公共方法调用 function _privateFunc() { return 0; ] } CMyFunc myFunc=new CMyFunc(); 使用:其它

UML类图与面向对象设计原则

1. 引言 从大一开始学习编程,到如今也已经有两年了.从最初学习的Html,Js,JaveSe,再到JavaEE,Android,自己也能写一些玩具.学习过程中也无意识的了解了一些所谓的设计模式,如今打算系统的学习.学习以书<设计模式的艺术——软件开发人员内功修炼之道/刘伟著>为主. 所谓设计模式,即是前人对某类相似问题的抽象给出的解决方案.书中给出了23(Gof)+1(简单工厂模式)种设计模式.每种模式的学习将关注以下几点:名称(Name),问题(Problem),解决方案(Solution

UML类图与面向对象设计原则&mdash;设计模式01

1. 引言     从大一开始学习编程,到如今也已经有两年了.从最初学习的Html,Js,JaveSe,再到JavaEE,Android,自己也能写一些玩具.学习过程中也无意识的了解了一些所谓的设计模式,如今打算系统的学习.学习以书<设计模式的艺术--软件开发人员内功修炼之道/刘伟著>为主.       所谓设计模式,即是前人对某类相似问题的抽象给出的解决方案.书中给出了23(Gof)+1(简单工厂模式)种设计模式.每种模式的学习将关注以下几点:名称(Name),问题(Problem),解决方

Javascript面向对象特性实现封装、继承、接口详细案例——进级高手篇

Javascript面向对象特性实现(封装.继承.接口) Javascript作为弱类型语言,和Java.php等服务端脚本语言相比,拥有极强的灵活性.对于小型的web需求,在编写javascript时,可以选择面向过程的方式编程,显得高效:但在实际工作中,遇到的项目需求和框架较大的情况下,选择面向对象的方式编程显得尤其重要,Javascript原生语法中没有提供表述面向对象语言特性的关键字和语法(如extends.implement).为了实现这些面向对象的特性,需要额外编写一些代码,如下.

JavaScript面向对象旅程(下)

JavaScript面向对象旅程 剪不断,理还乱,是离愁. 前面已经提到过新语言开发的两个步骤,分别是:一.定义基本的数据类型,完善结构化编程语言的设计:二.为函数类型绑定this的概念,好在对象的方法中可以引用到对象自身.下面是继续下去的思路,其主体思想是尽可能地引用传统面向对象语言的相关概念(如类.继承等)到新语言中来. 三.让对象属于某个类 这次要引入类的概念来.但是注意的是,还是前面提到过的思路,是让对象看起来属于某个类,而不是真正地构造基于类的种种语义概念. 一般来说,类包括类符号和类

再谈javascript面向对象编程

前言:虽有陈皓<Javascript 面向对象编程>珠玉在前,但是我还是忍不住再画蛇添足的补上一篇文章,主要是因为javascript这门语言魅力.另外这篇文章是一篇入门文章,我也是才开始学习Javascript,有一点心得,才想写一篇这样文章,文章中难免有错误的地方,还请各位不吝吐槽指正 吐槽Javascript 初次接触Javascript,这门语言的确会让很多正规军感到诸多的不适,这种不适来自于Javascript的语法的简练和不严谨,这种不适也 来自Javascript这个悲催的名称,

JavaScript面向对象精要(一)

传统面向对象的语言几大特征:封装.继承.多态,在JavaScript中并不适用.JavaScript的弱类型特征允许你用比其他语言更少的代码完成同样的任务.无需提前设计好类再进行编码.需要一个具有某个字段的对象了?随时随地都可创建.Nicholas C.Zakas著作<JavaScript面向对象精要>告知我们如何创建对象.定义自己的类型,使用继承以及其他各种操作来充分使用对象.总之,更全面理解和使用JavaScript所有的一切. 一.原始类型和引用类型 1. 什么是类型 JavaScrip