js面向对象学习 - 对象概念及创建对象
原文地址:js面向对象学习笔记
一、对象概念
对象是什么?对象是“无序属性的集合,其属性可以包括基本值,对象或者函数”。也就是一组名值对的无序集合。
对象的特性(不可直接访问),也就是属性包含两种,数据属性和访问器属性。
1、数据属性又包含
- Configurable //表示能否通过delete删除,默认为true;
- Enumerable //表示能否通过for-in循环返回属性,默认为true;
- Writable //表示能否修改属性的值,默认为true;
- Value //包含属性的数据值,默认为undefined
要修改默认属性的特性,必须使用ECMAscript5的object.defineProperty(属性的对象, 属性的名字, 需要修改的属性特性)方法。例如:
// 1、修改默认的属性特性, var person = {}; Object.defineProperty(person, "name", { writable : false, value : "abc" }); alert(person.name); //abc person.name = "bcd"; alert(person.name); //abc而不是bcd,这里在非严格模式下会忽略,在严格模式下会报错
一旦做了这样的设置之后,就不可再次修改了,否则就会报错。
// 1、修改默认的属性特性, var person = {}; Object.defineProperty(person, "name", { writable : false, value : "abc" }); Object.defineProperty(person, "name", { writable : true, });
还有一点要注意的是,在调用Object.defineProperty()方法时,如果不指定第三个参数中的(Configurable,writable,Enumerable),也就是要修改的属性,那么他们都会默认为false
// 1、修改默认的属性特性, var person = {}; person.sex = "nan"; Object.defineProperty(person, "name", { //在这里我们修改name的值,不指定第三个参数中的属性,看结果 // writable : false, value : "abc" }); alert(person.name); //abc person.name = "bcd"; alert(person.name); //abc,不可修改,默认为false person.sex = "nv"; //没有调用defineProperty,默认还是为true alert(person.sex); //nv
2、访问器属性
- Configurable
- enumerable
- get //在读取属性时调用的函数
- set //在写入属性时调用的函数
// 2、定义访问器属性 var book = { _year : 2014, edition : 1 } Object.defineProperty(book, 'year', { //year在这里就是定义访问器属性 get : function(){ return this._year; }, set : function(value){ this._year = value; this.edition += value-2004; } }); book.year = 2005; alert(book.edition); // 2
当需要定义多个属性时,可以使用defineProperties(对象, 需要添加的属性);
// 3、定义多个属性 var books = {}; Object.defineProperties(books, { _year : { value : 2004 }, edition : { value : 1 }, year : { get : function(){ return this._year; }, set : function(value){ this._year = value; this.edition += value-2004; } } }); // books.year = 2006; // alert(books._year); ////这里就不能用这个方法赋值了,这里返回2004 var descriptor = Object.getOwnPropertyDescriptor(books, "_year"); descriptor.value = 2006; alert(descriptor.value); //2006 // alert(typeof descriptor.get);
这些概念似乎用的地方比较少,但是去理解js对象是很有作用的,基础嘛,基础永远是必须的,继续学习~
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/*==========================================================================*/
(我发现等号分割线没上面短杠分割线好看)
二、创建对象
前几天看到这样的面试题,js创建对象的方法有几种,只知道是3种写法,并不清楚原理是什么,今天整理了下。
- 工厂模式
- 构造函数模式
- 原型模式
- 组合使用构造函数模式和原型模式
1、工厂模式
// 4、工厂模式 function createPerson(name){ var obj = new Object(); obj.name = name; obj.show = function(){ alert(this.name); } return obj; } var person = createPerson("ym");//不需要使用new person.show();
2、构造函数模式
构造函数的函数名大写开头,其他函数都是小写
// 5、构造函数模式 function Person(name, sex){ this.name = name; var sex = sex; //私有 this.show = function(){ alert(sex); } } var person1 = new Person('ym', 'nan'); alert(person1.name); //ym alert(person1.sex); //undefined person1.show(); //nan
与工厂模式的区别:
- 没有显示创建对象
- 直接赋值给this对象
- 没有return语句
构造函数的问题:
当对象有多个实例时,这些实例的所有方法都是不同的,因为它都会创建一遍。
// 5、构造函数模式 function Person(name, sex){ this.name = name; var sex = sex; //私有 this.show = function(){ alert(sex); } } var person1 = new Person('ym', 'nan'); var person2 = new Person('jh', 'nv'); // alert(person1 instanceof Person); //true alert(person1.show == person2.show); //false
3、原型模式
优点:可以让所有对象实例共享它所包含的属性和方法。
// 6、原型模式 function Person2(){} Person2.prototype = { name : "ym", sex : 'nan', show : function(){ alert(this.name); } } var a = new Person2(); var b = new Person2(); alert(a.show == b.show); //true
关于prototype,对它的理解也是非常重要的,过几天再学习整理,看了好多次了,觉得还是理解不够。
prototype是一个指针,指向一个对象,而这个对象就是包含所有实例共享的属性和方法,也就是说,通过调用构造函数而创建的那个对象实例的原型对象。
原型模式的问题:
// 6、原型模式 function Person2(){} Person2.prototype = { name : "ym", sex : 'nan', love : ['a', 'b'], show : function(){ alert(this.name); } } var a = new Person2(); a.love.push('c'); var b = new Person2(); a.love.push('d'); // alert(a.show == b.show); alert(a.love); //abcd alert(b.love); //abcd
4、组合使用原型模式和构造函数模式
通过以上的例子我们可以知道,构造函数模式,创建的方法都是不同的,都是实例自己拥有的,而原型模式定义的属性和方法是共享的,那么结合起来使用真是perfect。
// 6、混合模式 function Perfect(name, sex){ this.name = name; this.sex = sex; this.love = ['a' , 'b']; } Perfect.prototype = { constructor : Perfect, show : function(){ alert(this.love); } } var a = new Perfect('a', 'nan'); var b = new Perfect('b', 'nv'); a.love.push('c'); b.love.push('d'); a.show(); //abc b.show(); //abd
总算是整理完了,我也理解了原来创建对象的3种方法就是上面说的前3点,但最好用的是第4种。