JS中创建对象
JS中简单的创建对象的方法如下所示,
var person = new Object(); person.name = "lyx"; person.age = 12; person.sayHello = function () { return "how are you!" }; console.log(person.sayHello());
但最普遍和流行的方式就是创建对象字面量:
var flight = { airline: "Oceanic", number: 815, departure: { IATA: "SYD", time: "2004-09-22 14:55", city: "Sydney" }, arrival: { IATA: "LAX", time: "2004-09-23 10:42", city: "Los Angeles" } };
下面来看几个比较常用的创建对象的方法:(JavaScript高级程序设计)
//使用工厂模式创建对象 function createPerson(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 = createPerson("lyx", 23, "sdfsadf"); console.log(person1.name);
这种创建对象的方式没有区分对象的类型
//使用new关键字 //Tune()是一个构造函数 function Tune(song, artist) { this.title = song; this.artist = artist; this.concat = function () { return this.title + "-" + this.artist; } } var tune = new Tune("a", "b"); console.log(tune.title);
使用new创建了一个新对象,以这种方式调用构造函数实际上会经历一下4个步骤:
创建一个新对象
将构造函数作用域赋给新对象(this指向了这个新对象)
执行构造函数中的代码
返回新对象
如何创建具有私有属性的对象
例如:
//创建私有的属性 function PrivateTune(song, artist) { var title = song; var artist = artist; this.concat = function () { return title + " " + artist; } } var privateTune = new PrivateTune("b", "c"); console.log(privateTune.title);//undefined console.log(privateTune.concat());
title属性是私有的,访问表示未定义
对象的constructor属性。当对象创建完成后,就会拥有这个属性
console.log(tune.constructor == Tune);//true console.log(privateTune.constructor == PrivateTune);//true
Javascript还提供了一个instanceof运算符,验证原型对象与实例对象之间的关系。
构造函数在不返回值的情况下,默认会返回新对象的实例。
构造函数本身也是函数,只不过可以用来创建对象而已
function Person() { } Person.prototype.name = "lyx"; Person.prototype.age = 23; Person.prototype.job = "student"; Person.prototype.sayName = function () { console.log(this.name); }; var person = new Person(); person.sayName(); //lyx console.log(person.job);
构造函数都有一个prototype属性。这个属性包含一个对象(以下简称"prototype对象"),所有实例对象需要共享的属性和方法,都放在这个对象里面;那些不需要共享的属性和方法,就放在构造函数里面。
function Person(name, age, address) { this.name = name; this.age = age; this.address = address; this.friends = ["as", "bd"]; } Person.prototype = { constructor: Person, sayName: function () { console.log(this.name); } }; var p1 = new Person("lyx", 23, "sdsdsdsd"); var p2 = new Person("sdsd", 23, "sdsdsd"); p1.friends.push("IO"); //修改了p1的friends属性,没有影响p2 console.log(p1.friends); //[ 'as', 'bd', 'IO' ] console.log(p2.friends);//[ 'as', 'bd' ]
实例属性都是在构造函数中定义的,而由所有实例共享的属性都在原型中定义。修改了p1的friends属性不会影响到其他实例,因为他们都引用不同的数组。。
这种构造函数与原型模式的混合,是目前在ECMASCript中使用最广泛,认同度最高的一种创建自定义类型的方法,可以说,这是用来定义引用类型的一种默认模式。
这种模式的基本思想是创建一个函数,这个函数的作用是仅仅封装创建对象的代码,然后返回新创建的对象,但从表面上看,这个函数又很想是典型的构造函数。
function Person(name, age, address) { var o = new Object(); o.name = name; o.age = age; o.address = address; o.sayName = function () { console.log(this.name); } return o; } var person = new Person("lyx", 23, "ssdsd"); console.log(person.name); //lyx
这种模式其实和工厂模式是一样的。
注意:
console.log(person.constructor == Person); //false console.log(person.constructor === Person); //false console.log(person instanceof Person);//false
稳妥构造函数模式遵循与寄生构造函数类似的模式,但有两点不同:
一个新创建对象的实例方法不引用this;
二是不使用new操作符调用构造函数。
如下实例:
function Person(name, age, address) { var o = new Object(); o.name = name; o.age = age; o.address = address; //定义私有变量和函数 var person_nickname = "ccccc"; var person_realname = "121212"; o.sayName = function () { console.log(this.name); }; o.sayPersonSecret = function () { console.log(person_nickname); } return o; } var person = Person("lyx", 23, "ssdsd"); console.log(person.name); //lyx person.sayPersonSecret(); //ccccc
注意:
console.log(person.constructor == Person); //false console.log(person.constructor === Person); //false console.log(person instanceof Person);//false
====END====