JavaScript之创建对象的方式

方式一:new 构造函数 Object,缺点:繁琐

构造函数与普通函数最大的区别在于:函数名首字母需要大写,eg:function Person(){ console.log("构造函数") }

var obj = new Object();
obj.name = "xcc";
obj.age = 18;
obj.say = function () {
      console.log("hello")  
   }
console.log(obj) 

方式二:工厂函数批量创建对象,把创建对象的过程进行了封装,并且返回创建出来的对象,缺点:不知道对象的具体类型,都是Object类型

function createPerson(name, age){
       var obj = {
       // 前面name为对象的属性名
       // 后面name是值,形参
       name: name,
        age: age
}
// 把obj返回出去,外面可以拿到该对象使用
return obj;
}
var o1 = createPerson("xm", 20);
console.log(o1);
var o2 = createPerson("xh", 18);
console.log(o2);

方式三:自定义构造函数创建对象

通过构造函数创建对象可以识别对象的具体类型(解决工厂函数的缺点问题)

function Person(name, age){
            // this.xxx = yyy; 这种形式来给创建出来的对象添加属性和方法
            this.name = name;
            this.age = age;
            this.saiHi = function () {
                console.log("hi");
            }
}
// 创建对象
var p1 = new Person("xhei", 22);
console.log(p1);
var p2 = new Person("xhua", 21);
console.log(p2);
// new 做了四件事情
//  1. 创建一个新对象
//  2. 把this指向了新对象
//  3. 执行构造函数内的代码
//  4. 返回新创建的对象

构造函数创建对象的问题?

// 构造函数创建对象的问题: 浪费内存
        
        function Person(name, age){
            this.name = name;
            this.age = age;
            this.sayHi = function () {
                console.log("hi");
            };
        }
        var p1 = new Person("xm", 20);
        var p2 = new Person("xh", 21);
        // console.log(p1, p2);
        // 复杂数据类型在比较的时候,比较的是地址
        console.log( p1 == p2 ); // false
        // 两份sayHi方法功能是一样的,在内存中却是有两份一样的
        console.log( p1.sayHi == p2.sayHi ); // false

解决问题:
// fn函数放到构造函数的外面:确保在内存中只有一份
        // 把需要的方法放到全局中,可以解决内存浪费问题,但是也会带来全局污染问题
        /*function fn() { // 0x14
            console.log("hi");
        }
        function fn2() {
            console.log("running man");
        }
        function fn3() {
            console.log("work man");
        }*/


// 优化以上代码
// 1. 内存浪费问题要解决
// 2. 减少全局污染问题
// 全局中只有tools对象
        var tools = {
            fn: function () { // 0x14
                console.log("hi");
            },
            fn2: function () {
                console.log("running man");
            },
            fn3: function () {
                console.log("work man");
            },
            // ...
        }
        function Person(name, age){
            this.name = name;
            this.age = age;
            // 这样添加方法,会有内存浪费问题,sayHi方法在内存中会有好多份
            // this.sayHi = function () {}
            // fn带上(),表示fn被调用了,把fn的调用结果赋值给了sayHi方法
            // this.sayHi = fn(); // error , 仅仅是把fn函数的地址0x14给赋值过去
            this.sayHi = tools.fn;
            this.running = tools.fn2;
            this.work = tools.fn3;
        }
        var p1 = new Person("xm", 20);
        console.log(p1);
        var p2 = new Person("xh", 21);
        console.log(p2);
        // 地址是一样的
        // console.log(p1.sayHi == p2.sayHi); // true


        // 小结:
        //  解决内存浪费问题:思路
        //    1. 把需要的方法直接放到构造函数外面,可以确保该方法在内存中只有一份
        //      方法比较多,容易造成全局污染问题
        //    2. 把需要的方法添加一个对象中
        //      麻烦:创建构造函数,还需要自己手动去创建对象(存需要的方法)

 

posted @ 2020-09-15 19:59  大熊在这里  阅读(147)  评论(0)    收藏  举报