zoukankan      html  css  js  c++  java
  • JavaScript对象创建的七种方式

    方式一:简单的对象创建。

    <script type="text/javascript">
        /**
         * 在js中并不存在类,所以可以直接通过Object来创建对象
         * 但是使用如下方式创建,带来最大的问题是,由于没有类的约束
         * 无法实现对象的重复利用,并且没有一种约定,在操作时会带来问题
         */
        var person = new Object();
        person.name = "Leon";
        person.age = 33;
        person.say = function() {
            alert(this.name+","+this.age);
        }
    </script>

    在很多时候,如果在网络中传递,不能直接传递对象,在网络中传字符串比较好传,那么能不能通过字符串的方式创建对象?我们可以想到用xml来表示我们的对象。例如:

    <person>
        <id>1</id>
        <username>zhangsan</userame>
        <nickname>昵称</nickname>
        <age>23</age>
    </person>

    通过这样的字符串可以转化成Person对象,里面有Id属性,username属性等等。但是可以看出上面要传递的内容内容并不是很多,里面充斥着大量的标签,传输效率不高。我们希望用另外一种字符串传递方式来替代xml。于是有了新的传递方式json(JavaScript Object Notation)

    方式二:json

    json就是js的对象,但是它省去了xml中标签,而是通过{}来完成对象的说明。

    <script type="text/javascript">
        var person = {
            name:"张三",//通过属性名:属性值来表示,不同的属性通过,来间隔
            age:23,
            say:function() {
                alert(this.name+","+this.age);
            }//最后一个属性之后不能有,
        }
        
        person.say();
        /**
         * 通过json依然可以创建对象数组,创建的方式和js的数组一样
         */
        var ps = [
            {name:"Leon",age:22},
            {name:"Ada",age:33}
        ];
        for(var i=0;i<ps.length;i++) {
            alert(ps[i].name);
        }
        /**
         * 创建一组用户,用户的属性有
         * name:string,age:int,friends:array
         * java中的写法:
         * List<Person> ps = new ArrayList<Person>();
         * ps.add(new Person("Leon",22,["Ada","Alice"]));
         * ps.add(new Person("John",33,["Ada","Chris"]));
         * 把ps转换为json
         */
        ps = [
            {
                name:"Leon",
                age:22,
                friends:["Ada","Alice"]
            },
            {
                name:"John",
                age:33,
                friends:["Ada","Chris"]
            }
        ];
        </script>

    由于没有类的概念,这两种方式最大的问题是对象不能重用。可以通过工厂方式来创建对象。

    方式三:工厂

    <script type="text/javascript">
        /**
         * 通过工厂的方式来创建Person对象
         * 在createPerson中创建一个对象
         * 然后为这个对象设置相应的属性和方法
         * 之后返回这个对象
         */
        function createPerson(name,age) {
            var o = new Object();
            o.name = name;
            o.age = age;
            o.say = function() {
                alert(this.name+","+this.age);
            }
            return o;
        }
        /**
         * 使用工厂的方式,虽然有效的解决了类的问题,但是依然存在另外一个问题
         * 我们无法检测对象p1和p2的数据类型
         */
        var p1 = createPerson("Leon",22);
        var p2 = createPerson("Ada",33);
        p1.say();
        p2.say();
        //alert(typeof p1);//返回object
        //alert(p1 instanceof ?);//没有person类,instanceof不能用。
        </script>

    工厂方式无法检测p1和p2的数据类型,我们可以通过构造函数来创建

    方式四:通过构造函数(constructor)

    <script type="text/javascript">
        /**
         * 通过构造函数的方式创建,和基于工厂的创建类似
         * 最大的区别就是函数的名称就是类的名称,按照java的约定,第一个
         * 字母大写。使用构造函数创建时,在函数内部是通过this关键字来
         * 完成属性的定义
         */
        function Person(name,age) {
            this.name = name;
            this.age = age;
            //以下方式带来的问题是所有的对象都会为该行为分配空间
            this.say = function() {
                alert(this.name+","+this.age);
            }
        }
        /*
         * 通过new Person来创建对象
         */
        var p1 = new Person("Leon",22);
        var p2 = new Person("Ada",32);
        p1.say(); p2.say();
        /**
         * 使用构造函数的方式可以通过以下方式来检测
         * 对象的类型
         */
        alert(p1 instanceof Person);
        /**
         * 使用构造函数创建所带来的第一个问题就是每一个对象中
         * 都会存在一个方法的拷贝,如果对象的行为很多的话
         * 空间的占用率就会大大增加
         */
        alert(p1.say==p2.say);//false,说明不是同一个say
        </script>

    修改say方法位置,其他不动。将行为设置为全局的行为可以解决空间占用率的问题。

    <script type="text/javascript">
        function Person(name,age) {
            this.name = name;
            this.age = age;
            this.say = say;
        }
        /**
         * 将行为设置为全局的行为,如果将所有的方法都设计为全局函数的时候
         * 这个函数就可以被window调用,此时就破坏对象的封装性
         * 而且如果某个对象有大量的方法,就会导致整个代码中充斥着大量的全局函数
         * 这样将不利于开发
         */
        function say() {
            alert(this.name+","+this.age);
        }
        /*
         * 通过new Person来创建对象
         */
        var p1 = new Person("Leon",22);
        var p2 = new Person("Ada",32);
        p1.say(); p2.say();
        /**
         * 使用构造函数的方式可以通过以下方式来检测
         * 对象的类型
         */
        alert(p1 instanceof Person);
        alert(p1.say==p2.say);//true,说明是同一个say
        </script>

    将行为设置为全局行为,函数就可以被window调用,破坏了对象的封装性,不利于开发。我们可以用下一种方式,基于原型。

    方式五:基于原型(prototype)的创建方式

    基于原型的创建可以将属性和方法,设置为Person专有的,不能再通过window来调用

    <script type="text/javascript">
        function Person(){
            
        }
        Person.prototype.name = "Leon";
        Person.prototype.age = 23;
        Person.prototype.say = function() {
            alert(this.name+","+this.age);
        }
        var p1 = new Person();
        p1.say();
        //通过window没有办法调用say方法,如此就完成了封装
        // say();//报错,say is not defined
        </script>

    基于原型的创建虽然可以有效的完成封装,但是依然有一些问题

    1、无法通过构造函数来设置属性值

    2、当属性中有引用类型变量是,可能存在变量值重复

    <script type="text/javascript">
        function Person(){
            
        }
        Person.prototype = {
            constructor:Person,
            name:"Leon",
            age:30,
            friends:["Ada","Chris"],
            say:function() {
                alert(this.name+"["+this.friends+"]");
            }
        }
        var p1 = new Person();
        p1.name = "John";
        p1.say();//john[ada,chris]
        //会在原型中找friends,所以Mike是在原型中增加的
        p1.friends.push("Mike");//为p1增加了一个朋友
        var p2 = new Person();
        //此时原型中就多了一个Mike,这就是原型所带来的第二个问题
        p2.say();//leon ada chris mike
        </script>

    方式六:  原型(prototype)和构造(constructor)混合模式

    <script type="text/javascript">
    /**
     * 为了解决原型所带来的问题,此处需要通过组合构造函数和原型来实现对象的创建
     * 将属性在构造函数中定义,将方法在原型中定义
     * 这种有效集合了两者的优点,是目前最为常用的一种方式
     */
        function Person(name,age,friends){
            //属性在构造函数中定义
            this.name = name;
            this.age = age;
            this.friends = friends;
        }
        Person.prototype = {
            constructor:Person,
            //方法在原型中定义
            say:function() {
                alert(this.name+"["+this.friends+"]");
            }
        }
        //此时所有的属性都是保存在自己的空间中的
        var p1 = new Person("Leon",23,["Ada","Chris"]);
        p1.name = "John";
        p1.friends.push("Mike");
        p1.say();
        var p2 = new Person("Ada",33,["Leon"]);
        p2.say();
        </script>

    第七种方式  动态原型的方式

    <script type="text/javascript">
    /**
     * 为了让定义的方式更加符合java的需求,就把定义方法的原型代码放置到Person这个构造函数中
     */
        function Person(name,age,friends){
            //属性在构造函数中定义
            this.name = name;
            this.age = age;
            this.friends = friends;
            
            //不能使用重写的方式定义,因为重写会改变引用
            /*Person.prototype = {
                constructor:Person,
                //方法在原型中定义
                say:function() {
                    alert(this.name+"["+this.friends+"]");
                }
            }*/
            /**
             * 判断Person.prototype.say是否存在,如果不存在就表示需要创建
             * 当存在之后就不会在创建了
             */
            if(!Person.prototype.say) {//每new一次都会定义一次,所以需要判断。
                Person.prototype.say = function() {
                    alert(this.name+"["+this.friends+"]");
                }    
            }
        }
        
        //此时所有的属性都是保存在自己的空间中的
        var p1 = new Person("Leon",23,["Ada","Chris"]);
        p1.name = "John";
        p1.friends.push("Mike");
        p1.say();
        var p2 = new Person("Ada",33,["Leon"]);
        p2.say();
        </script>
  • 相关阅读:
    database design
    django bulk create user
    mysql basic
    install mysql
    django apache httpd windows
    django apache httpd centos
    python mail smtplib
    compile c cpp with cl.exe in vim
    Remote Access to IPython Notebooks via SSH
    calculate traffic by snmpwalk for mrtg
  • 原文地址:https://www.cnblogs.com/songzongyuan-java/p/9564482.html
Copyright © 2011-2022 走看看