一、对象的特点
对象,就是类。类,就是具有相同的属性和方法。但是,js里面没有类的概念。
ヾ(=・ω・=)o 孔乙己曾经说过,茴香豆的“茴”字有4种写法,那么作为‘迂腐’的程序员,也得知道js创建对象的常用4种方法吧! ヾ(=・ω・=)o
二、js创建对象的方法
js创建对象常用的有4种方法,Object构造函数、对象字面量和工厂函数、自定义构造函数模式。
前两个一次只能创造一个对象,后两个可以大批量创造对象。
工厂函数:没有办法检验你创建的对象类型。
自定义构造函数模式:可创建特定类型的对象。
1、Object构造函数
//1-Object构造函数 var person1=new Object(); person1.name='Alice'; person1.age=18; person1.sayName=function(){ console.log(this.name); } person1.sayName(); //Alice
2、对象字面量
//2-对象字面量,注意隔开用的是逗号,表示用的是冒号 var person2={ name:'Tony', age:19, sayName:function(){ console.log(this.name); } } person2.sayName();//Tony
3、工厂函数,不是用new操作符,没有办法检查他是什么类型的,只能检查到他是Object
function person3(name,age,sayName){ var obj=new Object(); obj.name=name; obj.age=age; obj.sayName=function (){ console.log(this.name); } return obj; } var person3_1=person3('NamJoon',24); person3_1.sayName();//NamJoon console.log(person3_1 instanceof Object);//true
4、自定义构造函数,可以检查到他的函数名称,这也是他比工厂函数高级的地方
//4-构造函数模式,注意,一定要大写,与其他方法区分开。方法一般是小写 function Person4(name,age,sayName){ this.name=name; this.age=age; this.sayName=function(){ console.log(this.name); } } var person4_1=new Person4('Jin',25); var person4_2=new Person4('suga',27); person4_2.sayName();//suga var cons=person4_1.constructor===person4_2.constructor;//注意这个属性,他们都指向Person4。 console.log(cons);//true console.log(person4_1.constructor);//Person4 //注意,这两个person的类型既是Person4,也是Object console.log(person4_1 instanceof Object);//true
扩展问题:当你使用new的时候,到底经历了什么?
(1)创建一个新对象
(2)将构造函数的作用域赋给新对象,因此,this指向这个新对象
(3)执行构造函数中的代码
(4)返回新对象
//在某个对象的作用域内调用构造函数 var obj=new Object(); Person4.call(obj,'BTS',100); obj.sayName();//BTS
三、构造函数模式本身存在的缺陷——原型模式出现,拯救无法封装的缺陷
在上面,Person4创建的对象中,有个sayName的属性,该属性是个方法。为了简便,把这个方法拿到全局里,让sayName这个属性存储的只是一个指针,指向全局里的sayName方法。
function Person4(name,age,sayName){ this.name=name; this.age=age; this.sayName=sayName(); } function sayName(){ console.log(this.name); }
如果这个对象有很多方法的话,那不就是要在全局里面写很多方法了吗?谁都能调用这些全局方法,那么这个所谓的自定义函数,就违背了封装性的概念了。所以,原型模式出现了。
function Person(){ } Person.prototype.name='Alice'; Person.prototype.age=18; Person.prototype.sayName=function(){ console.log(this.name); } var person1=new Person(); person1.sayName();//Alice var person2=new Person(); person2.name='王花花'; person2.sayName();//王花花
在上面这段代码中,构造函数变成了空函数,但是照样可以用它来生产对象。这是因为,
任何函数,都会有一个prototype属性。这个属性,指向函数的原型对象。在js中,函数与对象的关系,可以理解为相等,函数就是对象,对象就是函数。
原型对象是天然美女,没有加工过的。通过实例化后,不动他的属性,他就不变。而实例化后,如果又改变了他的属性,就有点像整容了,他的属性就变成了他整容之后的样子。也就是下面的那个‘王花花’。
四、获取对象里的属性和方法
两个:for in 和Object.keys(对象名)
function Person4(name,age,sayName){ this.name=name; this.age=age; this.sayName=sayName; } function sayName(){ console.log(this.name); } for (var item in Person4){ console.log(item);//Array(3) ["name", "age", "sayName"] } var keys=Object.keys(Person4); console.log(keys);//Array[0],这是为什么呢?就因为没有给他添加值吗? var p1=new Person4(); p1.name='alice'; p1.age=19; var p1Keys=Object.keys(p1); console.log(p1Keys);//Array(3) ["name", "age", "sayName"] for(var item in p1){ console.log('item-->'+item);//name,age,sayName console.log(typeof item);//3个string,不是数组 }