js 创建对象的几种方式

对象可以通过两种形式定义:声明(文字)形式和构造形式
1)对象字面量:

var obj = {
    key:value
    //...
}

2)构造函数

var obj = new Object();
obj.key = value;

虽然Object构造函数或对象字面量可以用来创建单个对象,但这些方式有个明显的缺点:一个接口创建很多对象,会造成大量的重复代码。为解决这个问题,开始使用工厂模式的一种变体。

工厂模式

function createPerson(name,age,sex){
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.sex = sex;
    obj.sayName = function(){
        return this.name;
    }
    return obj;
}
var per1 = createPerson('Rose',18,'female');
per1.sayName();//Rose
var per2 = createPerson('Jack',19,'male');
per2.sayName();//Jack

工厂模式虽然解决了多个相似对象的问题,但未解决对象识别的问题(即:怎知一个对象的类型)。

构造函数

function Person(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.sayName = function(){
        return this.name;
    }
}
var per1 = new Person('Rose',18,'female');
per1.sayName();//Rose
var per2= new Person('Jack',19,'male');
per2.sayName();//Jack

与工厂模式的不同之处:
1)没有显式地创建对象;
2)直接将属性和方法赋给了this对象;
3)没有return语句返回对象。

根据惯例,构造函数有几点特点:1)构造函数以大写字母开头,非构造函数以小写字母开头;2)创建构造函数的新实例时,必须使用new操作符。

使用构造函数的主要问题是:同样的操作,但每个方法都需在实例上创建一遍

通过把函数转移到构造函数外,来解决这个问题

function Person(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.sayName = sayName;
}
function sayName(){
    return this.name;
}
var per1 = new Person('Rose',18,'female');
per1.sayName();//Rose
var per2= new Person('Jack',19,'male');
per2.sayName();//Jack

我们将sayName属性设置成全局的sayName函数,若对象定义了多个方法,那么我们将定义多个全局函数,就无封装性可言了,因此我们使用原型模式解决问题。

原型模式

function Person(){}
Person.prototype.name = 'Rose';
Person.prototype.age = 18;
Person.prototype.sex = 'female';
Person.prototype.sayName = function(){
    return this.name;
}
var per1 = new Person();
per1.sayName();//Rose
var per2 = new Person();
per2.sayName();//ROse
console.log(per1.sayName() === per2.sayName());//true,新对象的这些属性和方法是由所有实例共享的。

更简单的原型语法:用一个包含所有属性和方法的对象字面量来重写整个原型对象

function Person(){}
Person.prototype = {
    constructor: Person,
    name: 'Rose',
    age: 18,
    sex: 'female',
    sayName: function(){
        return this.name;
    }
}
var per1 = new Person();
per1.sayName();//Rose
var per2 = new Person();
per2.sayName();//Rose

注:将Person.prototype设置为等于一个以对象字面量形式创建的新对象,最终结果不变,但constructor属性不再指向Person,本质上完全重写了默认的prototype对象,因此constructor属性也变成了新对象的constructor,即指向Object构造函数。若constructor的值很重要,可以特意将它设置回适当的值,如:constructor: Person

原型模式最大的问题就是由其共享特性造成的,对于包含引用类型的属性来说,问题就更加明显了。

function Person(){}
Person.prototype = {
    constructor: Person,
    name: 'Rose',
    age: 18,
    sex: 'female',
    friends: ['Jack','Joe'],
    sayName: function(){
        return this.name;
    }
}
var per1 = new Person();
per1.friends.push('John');
var per2 = new Person();
console.log(per1.friends);//["Jack", "Joe", "John"]
console.log(per2.friends);//["Jack", "Joe", "John"]
console.log(per1.friends === per2.friends);//true

由于friends数组属性存在于Person.prototype属性中,而非per1中,所以在per1中修改friends数组的属性值,也同样会反应在per2中,这并不是我们想要的结果,这就是我们很少看到单独使用原型模型的问题所在。

组合使用构造函数和原型模式

构造函数模式定义实例属性,原型模式定义共享方法和共享属性

function Person(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.friends = ['JJ','Joe'];
}
Person.prototype = {
    constructor: Person,
    sayName: function(){
        return this.name;
    }
}
var per1 = new Person('Rose',18,'female');
per1.friends.push('John');
var per2 = new Person('Jack',19,'male');
console.log(per1.friends);//["JJ", "Joe", "John"]
console.log(per2.friends);//["JJ", "Joe"]
console.log(per1.friends === per2.friends);//false
console.log(per1.sayName === per2.sayName);//true

构造函数和原型模式混成的模式,是ECMAScript中使用最广泛、认同度最高的一种创建自定义类型的方法。

动态原型模式

在其他OO语言经验的开发人员在看到独立的构造函数和原型时,很可能会感到困惑。动态原型模式致力于解决这个问题,它将所有信息都封装在构造函数中。

function Person(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
    if(typeof this.sayName != 'function'){
        Person.prototype.sayName = function(){
            return this.name;
        }
    }
}
var per1 = new Person('Rose',18,'female');
per1.sayName();

使用动态原型模式时,不能使用对象字面量重写原型。如果在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系。

寄生构造函数模式

基本思想:创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象。

function Person(name,age,sex){
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.sex = sex;
    obj.sayName = function(){
        return this.name;
    }
    return obj;
}
var per1 = new Person('Rose',18,'female');
per1.sayName();

除了使用new操作符并把使用的包装函数叫做构造函数之外,这个模式与工厂模式一模一样。
注:返回的对象域构造函数或者与构造函数的原型属性之间没有关系,即:构造函数返回的对象与在构造函数外部创建的对象没有什么不同,因此,不能依赖 instanceof 操作符来确定对象类型。

稳妥构造函数模式

稳妥对象:指没有公共属性,而且其方法也不引用this对象(禁止使用new和this)。

function Person(name,age,sex){
    var obj = new Object();//创建要返回的对象
    obj.name = name;//定义私有变量
    obj.age = age;
    obj.sex = sex;
    obj.sayName = function(){//创建方法
        return this.name;
    }
    return obj;//返回对象
}
var per1 = Person('Rose',18,'female');
per1.sayName();//Rose

per1就是一个稳妥对象,除了sayName方法,没有其它途径去获取Person的name属性。
注:与寄生构造函数模式类似,使用稳妥构造函数创建的对象与构造函数没有什么关系,因此使用instanceof操作符对这种对象也没有意义。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: JavaScript创建对象几种方式包括: 1. 对象字面量:使用花括号{}创建一个对象,可以在其中定义属性和方法。 2. 构造函数:使用关键字new和一个函数来创建一个对象,可以在函数中定义属性和方法。 3. Object.create()方法:使用一个现有的对象作为原型来创建一个新的对象,可以在新对象中添加或修改属性和方法。 4. 工厂函数:使用一个函数来创建对象,该函数返回一个新的对象,可以在函数中定义属性和方法。 5. ES6中的类:使用class关键字来定义一个类,可以在类中定义属性和方法,使用new关键字来创建一个对象。 ### 回答2: JavaScript是一门面向对象的脚本语言,因此创建对象在其中是非常重要和基础的一环。 JavaScript创建对象方式可以分为以下几种: 1. Object构造函数 Object是JavaScript中的内建构造函数,它可以创建一个空对象或者通过传递参数创建具有属性的对象。 例子: ``` var obj = new Object(); //创建一个空对象 var car = new Object(); //创建有属性的对象 car.brand = "BMW"; car.color = "blue"; ``` 2. 对象字面量 对象字面量是一种简便的创建对象方式,它可以直接将属性与属性值的对应关系写在一起,通过花括号{}进行标识。 例子: ``` var obj = {}; //创建一个空对象 var car = { //创建有属性的对象 brand: "BMW", color: "blue" }; ``` 3. 构造函数 可以使用函数作为模板来创建对象,这样的函数就被称为构造函数。通过使用new关键字去实例化这个函数创建一个对象。 例子: ``` function Car(brand, color) { //定义构造函数 this.brand = brand; this.color = color; } var myCar = new Car("BMW", "blue"); //实例化构造函数,创建对象 ``` 4. 原型 JavaScript的原型实现了面向对象的继承机制,对象继承其原型的属性和方法。因此可以通过原型来创建对象。 例子: ``` function Car() { //定义构造函数 } Car.prototype.brand = "BMW"; //在原型上定义属性 var myCar = new Car(); //实例化构造函数,创建对象 console.log(myCar.brand); //输出"BMW" ``` 以上是JavaScript中创建对象几种方式,它们各自具有优点和适用范围。我们可以根据自己的实际需要,选择最适合的方式创建对象。 ### 回答3: JavaScript创建对象方式有多种,常用的有: 1.字面量方式:使用对象字面量创建对象 var person = { name: "John", age: 20, gender: "male", sayHello: function() { console.log("Hello, my name is " + this.name); } }; 2.构造函数方式:使用构造函数创建对象 function Person(name, age, gender) { this.name = name; this.age = age; this.gender = gender; this.sayHello = function() { console.log("Hello, my name is " + this.name); } } var person = new Person("John", 20, "male"); 3.原型方式:使用原型创建对象 function Person() {} Person.prototype.name = "John"; Person.prototype.age = 20; Person.prototype.gender = "male"; Person.prototype.sayHello = function() { console.log("Hello, my name is " + this.name); } var person = new Person(); 4.简单工厂方式:通过一个工厂函数创建对象 function createPerson(name, age, gender) { var person = {}; person.name = name; person.age = age; person.gender = gender; person.sayHello = function() { console.log("Hello, my name is " + this.name); } return person; } var person = createPerson("John", 20, "male"); 5.构造函数和原型组合方式:使用构造函数和原型结合创建对象 function Person(name, age, gender) { this.name = name; this.age = age; this.gender = gender; } Person.prototype = { constructor: Person, sayHello: function() { console.log("Hello, my name is " + this.name); } }; var person = new Person("John", 20, "male"); 以上是JavaScript创建对象的常见方式,不同的方式都有各自的优缺点,选择合适的方式可以提高执行效率和开发体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值