js中创建对象的几种方式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
</head>
<body>
</body>
<script>
    //一:创建单个对象的两种方式

    //1:通过new 操作符 加上Object 构造函数去创建
    var person = new Object();
    person.name = "zhangsan";
    person.age = 18;
    person.job = "frontend";
    person.sayName = function () {
        alert(this.name);
    };
    console.log(person);
    // 如果创建的对象包含大量的属性,代码会很多,
    // 为了简化创建大量属性的过程,因此出现了对象定义的简写形式,对象字面量。

    //2:通过对象字面量,花括号,键值对的方式去创建。
    var person2 = {
        name: "lisi",
        age: 20,
        job: "frontend",
        sayname: function () {
            alert(this.name);
        }
    };
    console.log(person2);
    // 以上两种方法是用来创建单个对象,但是如果创建多个相似的对象时,会产生大量重复的代码因此产生了工厂函数

    // 二:创建多个相似的对象的两种方式
    //1:工厂模式
    function ceratPerson(name, age, job) {
        // 原生构造函数,运行时会自动出现在执行环境中
        var o = new Object();
        o.name = name;
        o.age = age;
        o.job = job;
        o.sayName = function () {
            alert(this.name);
        };
        return o;
    }
    //可以创建多个相似的对象,同时代码量也减少了很多
    var person1 = ceratPerson("zhangsan", 18, "frontend");
    var person2 = ceratPerson("lisi", 20, "frontend");
    console.log(person1);
    console.log(person1.constructor);//function Object() { [native code] }
    //但是没有解决对象的标识性问题,就是无法判断创建出来的对象是什么类型的,因此出现了构造函数

    //2:构造函数,创建特定类型的对象
    function Person(name, age, job) {
        this.name = name;
        this. age = age;
        this.job = job;
        this.sayName = function () {
            alert(this.name);
        }
    }
    var person1 = new Person("zhangsan", 18, "frontend");
    var person2 = new Person("lisi", 20, "frontend");
    console.log(person1);
    console.log(person1.constructor);
    /*  function Person(name,age,job){
     this.name = name;
     this,age  = age;
     this.job = job;
     this.sayName = function  () {
     alert(this.name);
     }
     }*/
    // 相对于工厂函数来说,解决了对象的标识性问题,同时代码也更加简洁。

    //把构造函数当做函数
    function Person(name, age, job) {
        this.name = name;
        this, age = age;
        this.job = job;
        this.sayName = function () {
            alert(this.name);
        }
    }
    //当做构造函数使用
    var person1 = new Person("zhangsan", 18, "frontend");
    person1.sayName();//zhangsan
    //当做普通函数使用
    Person("lisi", 20, "frontend"); // 添加到window
    window.sayName();//lisi
    // 在另一个对象的作用域中调用
    var o = new Object();
    Person.call(o, "wangwu", 25, "frontend");
    o.sayName();

    //构造函数存在的问题
    //方法无法复用,每个person实例都包含一个不同的function实例
    function Person(name, age, job) {
        this.name = name;
        this. age = age;
        this.job = job;
        this.sayName = function () {
            alert(this.name);
        }
    }
    var person1 = new Person("zhangsan", 18, "frontend");
    var person2 = new Person("lisi", 20, "frontend");
    alert(person1.sayName == person2.sayName);//false

    //解决办法:
    //sayName 属性设置成全局的sayName函数
    //该方法的缺点:
    // 1>全局函数只能被该构造函数创建的一类对象调用,名不符合
    // 2>如果方法很多,就会定义很多全局函数,代码冗余,自定义的引用类型就没有任何封装性可言
    function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
        this.sayName = sayName;
    }
    function sayName() {
        alert(this.name);
    }
    var person1 = new Person("zhangsan", 18, "frontend");
    var person2 = new Person("lisi", 20, "frontend");
    alert(person1.sayName == person2.sayName);//true

    //3: 原型模式,实现方法的共享
    function Person() {
    }
    Person.prototype.name = 'tom';
    Person.prototype.age = 16;
    Person.prototype.friend = ['zhangsan', 'lisi'];
    Person.prototype.job = 'frontend';
    Person.prototype.sayName = function () {
        alert(this.name);
    };
    var person1 = new Person();
    var person2 = new Person();
    person1.sayName();//tom
    person2.sayName();//tom
    alert(person1.sayName == person2.sayName);
    //如果想改写属性,可直接在实例上添加属性值;
    person1.name = 'jerry';
    person1.sayName(); // jerry
    person2.sayName(); // tom
    // 但是如果该属性值为引用数据类型的话,就会影响其他所有的实例对象
    person1.friend.push('zhaoliu');
    console.log(person1.friend);//["zhangsan", "lisi", "zhaoliu"]
    console.log(person2.friend);//["zhangsan", "lisi", "zhaoliu"]
    //原型模式最大的问题是由其共享的本质导致的,而引用数据类型的储存方式造成了实例化对象之间的相互影响。
    //为了解决这个问题,提出构造函数和原型混合的模式。

    //4.构造函数和原型混合模式
    function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
        this.friend = ['zhangsan', 'lisi'];
    }
    Person.prototype.sayName = function () {
        alert(this.name);
    };
    var person1 = new Person("zhangsan", 18, "frontend");
    var person2 = new Person("lisi", 20, "frontend");
    //如果想改写属性,可直接在实例上添加属性值;
    person1.name = 'jerry';
    console.log(person1.name);
    console.log(person2.name);
    // 如果该属性值为引用数据类型的话,因为引用数据类型的属性是在构造函数中,所以实例间数据不会影响
    person1.friend.push('zhaoliu');
    console.log(person1.friend);//["zhangsan", "lisi", "zhaoliu"]
    console.log(person2.friend);//["zhangsan", "lisi"]

    //5:为了更好的体现封装性,可在构造函数中初始化原型,同时又保持使用构造函数和原型的优点;
    //通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型
    function Person(name, age, job) {
        this.name = 'tom';
        this.age = 16;
        this.job = 'frontend';
        this.friend = ['zhangsan', 'lisi'];
        if (typeof this.sayName != "function") {
            Person.prototype.sayName = function () {
                alert(this.name);
            }
        }
    }
    var person1 = new Person("zhangsan", 18, "frontend"); // jerry
    var person2 = new Person("lisi", 20, "frontend"); // tom
    person1.friend.push('zhaoliu');
    console.log(person1.friend);//["zhangsan", "lisi", "zhaoliu"]
    console.log(person2.friend);//["zhangsan", "lisi"]
</script>
</html>
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值