• Javascript create Object(define new Class)


    JavaScript创建新类(或对象)的方法主要有以下几种:工厂方式、构造函数式、原型方式、混合的构造函数/原型方式、动态原型方法、混合工厂方式。

    1.工厂方式:

    function say() {
        document.write(
    this.name+"<br/>");
    }
    function people(name, age, sex) {
       
    var pTemp = new Object;
        pTemp.name
    = name;
        pTemp.age
    = age;
        pTemp.sex
    = sex;
        pTemp.say
    = say;
       
    return pTemp;
    }
    var tom = people("Tom", 6, "male");
    var marry = people("Marry", 16, "female");
    tom.say();    
    //outputs "Tom"
    marry.say();  //outputs "Marry"
    //tom inherits the constructor property from Object.prototype;
    document.write((tom.constructor == new Object().constructor)+"<br/>"); //output "true"
    //But constructor property doesn`t belong to tom.
    document.write((tom.hasOwnProperty("constructor")) + "<br/>"); //output "false"
    // prototype also does not belong to tom.
    document.write((tom.hasOwnProperty("prototype")) + "<br/>"); //output "false"
    document.write((tom.prototype == new Object().prototype) + "<br/>"); //output "true"
    document.write((marry.prototype == new Object().prototype) + "<br/>"); //output "true"
    document.write((people.prototype == Function.prototype) + "<br/>"); //output "false"
    document.write((marry.prototype == Function.prototype) + "<br/>"); //output "false"

    工厂方式的缺点是:

    1. 没有类的概念,在创建一个新的类型时,需要新创建一个新的工厂方法,不具有OO的特征;

     

    2.构造函数式

    function Person(name, age, sex) {
       
    this.name = name;
       
    this.age = age;
       
    this.sex = sex;
       
    this.say = function () {
            document.write(
    this.name + "<br/>");
        }
    }
    var tom = new Person("Tom", 6, "male");
    var marry = new Person("Marry", 16, "female");
    tom.say();    
    //outputs "Tom"
    marry.say();  //outputs "Marry"

    document.write((tom.constructor == Person) + "<br/>"); //output "true"
    document.write((tom.prototype == Person.prototype) + "<br/>"); //output "false"
    document.write((tom.prototype == marry.prototype) + "<br/>"); //output "true"

    //普通对象没有prototype对象,对对普通对象的prototype进行比较,也说明不了任何东西

    document.write((marry.prototype == new Object().prototype) + "<br/>"); //output "true"

    document.write((marry.prototype == Function.prototype) + "<br/>"); //output "false"

    document.write((Person.prototype == Function.prototype) + "<br/>"); //output "false"
    document.write((Person.prototype == Object.prototype) + "<br/>"); //output "false"

    构造函数式的缺点是say这个方法定义在函数类中,这样每个对象都有这么一个函数,是一种资源浪费。

    3.原型方式

    使用prototype属性可以很好的扩这类的方法和属性。使用方法为: object.prototype.name=value

    function Person() {
        Person.prototype.name
    = "smith";
        Person.prototype.age
    = 3;
        Person.prototype.sex
    = "male";
        Person.prototype.lessons
    = new Array("mathematics", "physics", "geography");
        Person.prototype.say
    = function () {
            document.write(
    this.name + "<br/>");
        }
    }
    var tom = new Person();
    var marry = new Person();
    tom.lessons.push(
    "biology");
    document.write(tom.lessons
    + "<br/>");     //outputs "mathematics,physics,geography,biology"
    document.write(marry.lessons + "<br/>");  //outputs "mathematics,physics,geography,biology"

    document.write((Person.prototype
    == Function.prototype)+ "<br/>");// output "false"
    document.write((tom.constructor == Person) + "<br/>"); //output "true"

    document.write((tom.constructor
    == new Object().constructor) + "<br/>"); //output "false"
    document.write((Person.prototype == tom.prototype) + "<br/>"); //output "false"
    //普通对象没有prototype对象,对对普通对象的prototype进行比较,也说明不了任何东西
    document.write((tom.prototype == new Object().prototype) + "<br/>"); //output "true"
    document.write((marry.prototype == new Object().prototype) + "<br/>"); //output "true"
    document.write((marry.prototype == Function.prototype) + "<br/>"); //output "false"
     
    document.write((Person.prototype == Function.prototype) + "<br/>"); //output "false"
    document.write((Person.prototype == Object.prototype) + "<br/>"); //output "false"

    从以上输出的结果看,原型方式定义的属性,如果属性指向的是对象,而不是函数的时候,对象的共享问题就会显现出来,多个实例的属性共享一个对象,示例中lessons属性是指向Array对象的指针,如果其中一个实例更改了属性,其它的实例也会跟着一起被更改,确切的来说就是所有的实例的该属性共用了一个内存地址。


    4.构造函数/原型混合方式(推荐方式)

    function Person(name, age, sex) {
       
    this.name = name;
       
    this.age = age;
       
    this.sex = sex;
       
    this.lessons = new Array("mathematics", "physics", "geography");
    }

    Person.prototype.say
    = function () {
        document.write(
    this.name);
    }
    var tom = new Person("Tom", 6, "male");
    var marry = new Person("Marry", 16, "female");

    tom.lessons.push(
    "biology");

    document.write(tom.lessons
    + "<br/>");     //outputs "mathematics,physics,geography,biology"
    document.write(marry.lessons + "<br/>");  //outputs "mathematics,physics,geography"

    document.write((Person.prototype
    == Function.prototype)+ "<br/>");// output "false"
    document.write((tom.constructor == Person) + "<br/>"); //output "true"

    document.write((tom.constructor
    == new Object().constructor) + "<br/>"); //output "false"
    document.write((Person.prototype == tom.prototype) + "<br/>"); //output "false"
    document.write((tom.prototype == new Object().prototype) + "<br/>"); //output "true"
    document.write((marry.prototype == new Object().prototype) + "<br/>"); //output "true"
    document.write((Person.prototype == Function.prototype) + "<br/>"); //output "false"
    document.write((Person.prototype == Object.prototype) + "<br/>"); //output "false"
    document.write((marry.prototype == Function.prototype) + "<br/>"); //output "false"

    采用构造函数/原型混合创建的方式,避免了属性为对象(非函数)时候的共享问题。


    5.动态原型方法(推荐方式)

    构造函数/原型混合方式创建虽然是可以的,有不少优点,但相对于标准的面向对象语言,构造函数/原型混合式的写法显然不那么美观,结果上也不是很合理,于是就有了动态原型方法。

    function Person(name, age, sex) {
       
    this.name = name;
       
    this.age = age;
       
    this.sex = sex;
       
    this.lessons = new Array("mathematics", "physics", "geography");

       
    //以下的Person不可以改成this,原因很简单,自己体会。
        if (typeof Person._initialized == "undefined") {
            Person.prototype.say
    = function () {
                alert(
    this.name);
            }
            Person._initialized
    = true;
        }
    }
    var tom = new Person("Tom", 6, "male");
    var marry = new Person("Marry", 16, "female");

    tom.lessons.push(
    "biology");

    document.write(tom.lessons
    + "<br/>");     //outputs "mathematics,physics,geography,biology"
    document.write(marry.lessons + "<br/>");  //outputs "mathematics,physics,geography"

    document.write((Person.prototype
    == Function.prototype)+ "<br/>");// output "false"
    document.write((tom.constructor == Person) + "<br/>"); //output "true"

    document.write((tom.constructor
    == new Object().constructor) + "<br/>"); //output "false"
    document.write((Person.prototype == tom.prototype) + "<br/>"); //output "false"
    document.write((tom.prototype == new Object().prototype) + "<br/>"); //output "true"
    document.write((marry.prototype == new Object().prototype) + "<br/>"); //output "true"
    document.write((Person.prototype == Function.prototype) + "<br/>"); //output "false"
    document.write((Person.prototype == Object.prototype) + "<br/>"); //output "false"
    document.write((marry.prototype == Function.prototype) + "<br/>"); //output "false"

    动态原型方法使用一个flag来判断这个函数是否已经被定义,如果被定义了,那么就不用重复定义了,这样看起来就更像Java/C#中类的定义了。

    6.混合工厂方式(不推荐使用)

    function Person(){
      
    var pTemp=new Object;
       pTemp.name
    ="smith";
       pTemp.age
    =2;
       pTemp.sex
    ="male";
       pTemp.say
    =function(){
           alert(
    this.name);
       }
      
    return pTemp;
    }
    var tom=new Person();
    var marry=new Person();

    tom.say(); 
    //smith
    marry.say();  //smith

    混合工厂式通常是在不能应用动态原型方式时的变通方法。它的目的是创建构造函数,只返回另一种对象的新实例。代码与工厂函数非常相似,区别主要在实例的创建上,工厂方式不需要用new关键字,混合工厂方式使用

    new关键字来创建实例,这又让它看起来像是构造函数。由于在Person内部调用了new运算符,程序将忽略第二个new运算符(new Person()),而是直接返回pTemp给var的变量。

  • 相关阅读:
    Electron-Builder 打包Nsis,安装后自动运行程序
    依赖倒置原则(DIP)、控制反转(IoC)、依赖注入(DI)(C#)
    六大设计原则(C#)
    C#简单爬取数据(.NET使用HTML解析器NSoup和正则两种方式匹配数据)
    简单架构:反射实现抽象工厂+IDAL接口完全独立DAL
    C#高级语法之泛型、泛型约束,类型安全、逆变和协变(思想原理)
    委托和lambda表达式,Action和Func
    .NET中使用WebService,以及和一般处理程序、类库的区别
    C#原型模式(深拷贝、浅拷贝)
    Thread、ThreadPool、Task、Parallel的基本用法、区别以及弊端
  • 原文地址:https://www.cnblogs.com/whyandinside/p/1818400.html
Copyright © 2020-2023  润新知