JavaScript稳扎记——创建对象的几种方式

本文详细介绍了JavaScript中通过字面式创建、new Object、工厂模式、构造函数、原型模式和构造函数+原型模式(PRO)六种创建对象的方式,以及它们的优缺点和适用场景,特别关注了原型模式的共享特性与构造函数模式的封装性.
摘要由CSDN通过智能技术生成

#Javascript是“基于prototype的语言 ”,且无法通过类来创建对象;
可以通过以下6种方式创建对象

一.字面式创建

方法:将成员信息写到{}中,赋值给一个变量,此时这个变量就是一个对象。

1.1定义方式

(1)采取键值对的形式
var 变量 { 属性:属性值,属性:属性值,…}

// 1.利用对象字面量创建对象 {}
  // var obj = {};  // 创建了一个空的对象 
        var obj = {
           uname: '张三疯',
           age: 18,
           sex: '男',
           sayHi: function() {
           console.log('hi~');

      }
    }
// (1) 里面的属性或者方法我们采取键值对的形式  键 属性名 : 值  属性值 
// (2) 多个属性或者方法中间用逗号隔开的
// (3) 方法冒号后面跟的是一个匿名函数
// 2. 使用对象
// (1). 调用对象的属性 我们采取 对象名.属性名 . 我们理解为 的
        console.log(obj.uname);
// (2). 调用属性还有一种方法 对象名['属性名']
        console.log(obj['age']);
// (3) 调用对象的方法 sayHi   对象名.方法名() 别忘记添加小括号
        obj.sayHi();

二、 new + Object创建对象

  方法:先通过object构造器new一个对象,再往里丰富成员信息。

2.1定义方式

*(1)利用 等号 = 赋值的方法
(2)属性和方法之间用 分号结束
*

// 利用 new Object 创建对象
        var obj = new Object(); // 创建了一个空的对象
        obj.uname = '张三疯';
        obj.age = 18;
        obj.sex = '男';
        obj.sayHi = function() {
                console.log('hi~');

            }
            // (1) 我们是利用 等号 = 赋值的方法 添加对象的属性和方法
            // (2) 每个属性和方法之间用 分号结束
        console.log(obj.uname);
        console.log(obj['sex']);
        obj.sayHi();

【】以上两种方法在使用同一接口创建多个对象时,会产生大量重复代码,为了解决此问题,工厂模式被开发*



三、 工厂模式

方法:使用一个函数来创建对象

3.1定义方式

  • 将对象构建的过程封装在一个函数中,这个函数能创建一个对象,
    并为他进行初始化赋值 ,最后返回这个对象;若要新建对象,直接调用这个函数即可。
  • 这种方式是使用一个函数来创建对象,减少重复代码,解决了前面三种方式的代码冗余的问题,但是方法不能共享的问题还是存在。

(1) 我们是利用 等号= 赋值的方法 添加对象的属性和方法
(2) 每个属性和方法之间用 分号结束


    // 使用工厂模式创建对象
	// 定义一个工厂方法
 function creatPerson(name,age) {
        var o = new Object();
        o.name = name;
        o.age = age;
        o.sayName = function () {
                
            alert('this.name');
        }
            return o;
        }
             var o1 = creatPerson('zhang',12);
             var o2 = creatPerson('js',12);
      
        
	//缺点:调用的还是不同的方法,浪费内存
	//没有解决对象识别的问题,因为全部都是Object
	
	//优点:解决了代码重复实例化多个对象的问题,逻辑简单
	alert(o1.sayName === o2.sayName); //false
	alert(o1 instanceof Object);// true
	
        


本例中,得到的都是o对象,对象的类型都是Object,因此出现了构造函数模式



四、 构造函数创建对象

方法:创建一个新对象
将构造函数的作用域赋给新对象(将this指向这个新对象)
执行构造函数代码(为这个新对象添加属性)
返回新对象

4.1 定义方式

# function 构造函数名() {
        this.属性 = 值;
        this.方法 = function() {}
     }  new 构造函数名();

(1) 构造函数名字首字母要大写 (见函数名首字母大写必为构造函数)
(2) 属性和方法前面必须添加 this
(3) 构造函数不需要return

 
        function Star(uname, age, sex) {
            this.name = uname;
            this.age = age;
            this.sex = sex;
            this.sing = function(sang) {
                console.log(sang);

            }
        }
        var ldh = new Star('刘德华', 18, '男'); // 调用函数返回的是一个对象
        // console.log(typeof ldh);
        console.log(ldh.name);
        console.log(ldh['sex']);
        ldh.sing('冰雨');
        var zxy = new Star('张学友', 19, '男');
        console.log(zxy.name);
        console.log(zxy.age);
        zxy.sing('李香兰')
  
 

        // 1. 构造函数名字首字母要大写
        // 2. 我们构造函数不需要return 就可以返回结果
        // 3. 我们调用构造函数 必须使用 new
        // 4. 我们只要new Star() 调用函数就创建一个对象 ldh  {}
        // 5. 我们的属性和方法前面必须添加 this

对比工厂模式有以下不同之处:
1、没有 return 语句
2、直接将属性和方法赋给了 this 对象
3、工厂函数针对的都bai是Object的对象模型,而构造函数可以匹配du定义的对象模型
4.构造函数弊端,如果在全局中定义相同的局部变量,容易造成全局污染,因为this.xx如果在局部获取不到,就会去全局中获取
5.构造函数可以重写,可以在全局中添加新属性和方法
Person.prototype = {},但工厂函数只能在局部添加

#优点:实例对象中的constructor属性指向了它的构造函数,proto属性指向了它的原型对象,因此完全可以确定该对象的类型。
确定对象类型的两种方式:
(推荐): 对象 instanceof 构造函数 (返回true/false)
(不推荐): 对象.constructor(直接获取其构造函数对象)
#缺点 :对象中所有的函数都需要重复定义,浪费内存
可以看出,构造函数知道自己从哪里来(通过 instanceof 可以看出其既是Object的实例,又是Person的实例)
构造函数也有其缺陷,每个实例都包含不同的Function实例( 构造函数内的方法在做同一件事,但是实例化后却产生了不同的对象,方法是函数 ,函数也是对象)



五、原型模式

方法:每个方法中都有一个原型(prototype),每个原型都有一个构造器(constructor),构造器又指向这个方法。
function Animal(){} alert(Animal.prototype.constructor==Animal);//true

5.1定义方式

  #通过原型创建对象,把属性和方法绑定到prototype上;
  #通过这种方式创建对象,方法是共享的,每个对象调用的是同一个方法。
	function Person() {
}

Person.prototype.name = "lisi";
Person.prototype.age = 21;
Person.prototype.family = ["lida","lier","wangwu"];
Person.prototype.say = function(){
    alert(this.name);
};
console.log(Person.prototype);   //Object{name: 'lisi', age: 21, family: Array[3]}

var person1 = new Person();        //创建一个实例person1
console.log(person1.name);        //lisi

var person2 = new Person();        //创建实例person2
person2.name = "wangwu";
person2.family = ["lida","lier","lisi"];
console.log(person2);            //Person {name: "wangwu", family: Array[3]}
// console.log(person2.prototype.name);         //报错
console.log(person2.age);              //21

//优点:由于原型对象被同一类型的所有对象共享,
//因此可以将函数 和 共享变量 定义在原型上,
//从而能避免重复创建对象,节约内存空间,并且能实现变量的共享。

//缺点:也正是因为原型拥有被同一类型的所有对象共享的特点,
// 因此如果将所有属性都定义在原型上,那么就不存在对象的实例属性了

#原型模式的好处是所有对象实例共享它的属性和方法(即所谓的共有属性),此外还可以如代码第16,17行那样设置实例自己的属性/方法(即所谓的私有属性),可以覆盖原型对象上的同名属性/方法。

六、构造函数+原型模式PRO(动态原型模式)

#  解决了原型模式的“破坏了封装性”的问题的
#  构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性

6.1定义方式

function Person(name,age,family){
    this.name = name;
    this.age = age;
    this.family = family;
}

Person.prototype = {
    constructor: Person,  //每个函数都有prototype属性,指向该函数原型对象,原型对象都有constructor属性,这是一个指向prototype属性所在函数的指针
    say: function(){
        alert(this.name);
    }
}

var person1 = new Person("lisi",21,["lida","lier","wangwu"]);
console.log(person1);
var person2 = new Person("wangwu",21,["lida","lier","lisi"]);
console.log(person2);

优点:和原型模式+构造函数模式相比,增加了封装性,更利于理解代码。
缺点:完美无缺

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值