javascript第一弹——对象

一、 什么是对象

对象是包含一组变量(称为属性)和函数(称为方法)的集合的实例。
javascript中大部分事物都是对象(有不同观点请留言讨论)
javascript有很多内建对象
javascript允许自定义对象
对象只是带有属性和方法的特殊数据类型
对象的属性是存储装载信息(属性值)的,可以理解为变量
对象的方法是执行其内部所包含的代码块的,可以理解为函数

注:以下所指对象均为自定义对象

二、 怎么创建对象

1、实例创建

//创建一个对象的实例
var handsomeMan = new Object();
handsomeMan.name='wyang';

字面量写法如下:

var handsomeMan = {};

2、工厂模式

function handsomeMan(){
    var o = new Object();
    o.name = 'wyang';
    o.sayName = function(){
        console.log(this.name);    //wyang
    }
    return o;
}
var me = handsomeMan();    //经典工厂模式
var me = new handsomeMan();    //混合工厂模式
me.sayName();

为了避免重复创建sayName方法,把上面的代码做了如下改进:

var sayName = function(){
    return this.name;    //wyang
}
function HandsomeMan(){
    var o = new Object();
    o.name = 'wyang';
    o.sayName = sayName;
}
var me = HandsomeMan();
me.sayName();

3、构造函数

function HandsomeMan(){
    this.name = 'wyang';
    this.sayName = function(){
        console.log(this.name);    //wyang
    }
}
var me = new HandsomeMan();
me.sayName();

为了避免重复创建sayName方法,把上面的代码做了如下改进:

var sayName = function(){
    return this.name;    //wyang
}
function HandsomeMan(){
    this.name = 'wyang';
    this.sayName = sayName;
}
var me = new HandsomeMan();
me.sayName();

4、原型模式

var sayName = function(){
    return this.name;    //wyang
}
function HandsomeMan(){};
HandsomeMan.prototype.name = 'wyang';
HandsomeMan.prototype.sayName = sayName;
var me = new HandsomeMan();
me.sayName();

5、混合模式(构造函数模式+原型模式)

function HandsomeMan(){
    this.name = 'wyang';
}
HandsomeMan.prototype.sayName = function(){
    console.log(this.name);    //wyang
}
var me = new HandsomeMan();
me.sayName();

三、 对象的属性是什么?

属性是存储装载其所对应对象的一些信息的容器;
对象中的属性是无序的,每一个属性都有一个字符串key和对应的 value;
不管设置的属性是否是字符串,javascript都会把它转换为字符串;

1、属性是可以动态添加或删除的。如下:

1
2
3
var obj = {};
obj.x = 1;
obj.y = 2;

2、对象中的每一个属性都有很多的属性标签,比如:

1
2
3
4
5
writable:能否修改属性的值; 默认值为 true;
enumerable:能否通过 for-in循环返回属性(是否可枚举); 默认值为 true;
configurable:能否删除、重新定义、修改属性特性、把属性修改为访问器属性/数据属性(是否能够配置); 默认值为true;
value:属性的数据值;可读写; 默认值为 undefined;
get/set:

  • 扩展:原型链

1
2
3
4
5
6
7
8
9
10
11
function HandsomeMan(){}
HandsomeMan.prototype.name = 'wyang';

//实例化对象
var obj = new HandsomeMan();
obj.age = 26;
obj.hobby = 'programme';

obj.age //26
obj.hobby //programme
obj.name //wyang

1)、上面的例子我们先定义了一个HandsomeMan的函数对象;HandsomeMan自带了一个prototype属性,它的属性是对象属性;
2)、HandsomeMan.prototype是一个对象;我们把这个对象添加一个属性name并赋值为wyang;
3)、用构造器的方式构造了一个新的对象obj;然后给这个对象添加了两个属性并赋值;然后通过访问这两个属性得到属性值;
4)、obj这个对象的原型会指向构造器的属性也就是HandsomeMan.prototype;
4)、[重点]当用obj.age访问age属性时,发现obj上有age这个属性,所以就会返回26hobby同理;但是当用obj.name来访问name时;发现obj上面没有name,这时它不会停止查找,而是继续向上查找他的原型也就是HandsomeMan.prototype;然后发现有name这个属性;所以返回wyang

如果给obj.name赋值,那么HandsomeMan.prototype.name的值会被修改么?

1
2
3
obj.name = 'wangyang';
obj.name //wangyang;
HandsomeMan.prototype.name //wyang

从上面的例子可以看出,如果给obj.name赋值,HandsomeMan.prototype.name的值是不会被修改的。因为obj对象里面有name这个属性,所以不会向上查找;

那么怎么再次通过obj对象拿到原型上的name呢?

1
2
delete obj.name;
obj.name //wyang

如上代码,通过删除obj.name后,就可以获得原型上的name;实际上这也就是原型链的继承;

四、 怎么给对象的属性赋值?

  • 键值对结构用“:”赋值;
  • 动态结构用“=”赋值;

五、 如何操作对像的属性?

1、读写对象的属性

1
2
3
4
5
6
7
8
9
var obj = {
name : 'wyang',
age : 26
}
obj.name; //wyang
obj['age']; //26

obj.hobby = 'programme';
obj['eat'] = 'food'; //当需要拼接对象的属性名或者用``for in``遍历所有属性的时候用‘[]’,其余的场景推荐使用‘.’;

2、属性异常

1
2
3
4
5
6
var obj = {
age: 26
}
obj.name; //undefined
obj.name.hobby //TypeError: Cannot read property 'hobby' of undefined
obj.name.hobby = 'programme'; //TypeError: Cannot read property 'hobby' of undefined

如果想对obj.name这个属性处理一些事情的话;需要先判断下obj.name是否存在:

1
2
3
4
var nh;     //var nh = obj && obj.name && obj.name.hobby;
if(obj.name){
nh = obj.name.hobby
}

3、删除属性

1
2
3
4
5
6
7
8
9
var obj = {
name : 'wyang',
age : 26
}
delete obj.name //true
delete obj['age'] //true
obj.name //undefined
obj.age //undefined
delete obj.name //如果重复删除已经不存在的属性,不会做任何事情,但是属性已经不存在了,javascript仍然会返回true;

1)、delete 并不代表操作成功,只是表示这个对象上并不存在这个属性;
2)、Object.prototype不能够被删除,因为它的configurable为false;所以删除会返回false;

  • 延伸:全局变量、局部变量、函数声明都不能通过delete被删除;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var a = 1;
delete a; //false
function a(){
var b = 1;
return delete b;
}
a() //false
function a(){}
delete a //false

//隐式创建的变量可以被删除(不推荐使用)
a = 1;
window.a; //1
delete.a //true

4、检测属性

1
2
3
4
5
6
7
8
9
10
11
//检测对象上是否含有某个属性
var obj = new Object;
obj.name = 'wyang';
obj.age = 26;

'name' in obj; //true
'hobby' in obj; //false
'toString' in obj; //true

obj.hasOwnProperty('name'); //true ‘obj’这个对象上包含‘name’这个属性;
obj.hasOwnProperty('toString'); //false

从上面的例子可以看出来:in操作符是会通过原型链向上查找的,它是作用于整个原型链的,所以不管是这个对象上的属性还是原型链上的属性都会返回‘true’;hasOwnProperty操作符是针对于当前对象的,不会去通过原型链向上查找;上面例子的‘obj’这个对象上没有包含‘ toString’这个属性;所以返回false;它的原型链上才有‘ toString’这个属性;

1
2
3
//检测对象上的某个属性是否可枚举
obj.propertyIsEnumerable('name'); //true
obj.propertyIsEnumerable('toString'); //false ‘Object.pertotype’上的大部分标签的‘enumerable’都是false;

5、枚举属性

1
2
3
4
5
6
7
8
9
var obj = {
name : 'wyang',
age : 26
}

var $property;
for($property in obj){
console.log($property); //name、age
}

上面例子通过for in来枚举当前对象上可枚举的属性;

1
2
3
4
5
6
var o = Object.create(obj);    //通过‘ Object.create’来船舰一个新对象,这个对象的原型指向‘obj’;
o.hobby = 'programme'; //默认可枚举
var $property;
for($property in obj){
console.log($property); //name、age、hobby
}

如果只想处理‘o’这个对象上的属性,不想处理这个对象原型链上的属性呢?

1
2
3
4
5
6
7
8
var o = Object.create(obj);    
o.hobby = 'programme';
var $property;
for($property in obj){
if(obj.hasOwnProperty($property)){ //只枚举当前对象上的属性,过滤掉这个对象原型链上的属性
console.log($property); //hobby
}
}

6、属性的get/set方法
get:在读取属性时调用的函数,默认值为 undefined
set:在写入属性时调用的函数,默认值为 undefined

1
2
3
4
5
6
7
8
9
10
11
12
var obj = {
name : 'wyang',
get age(){
return new Date().getFullYear() - 1989;
},
set age(val){
console.log('您不能修改年龄为'+val+'岁!!!');
}
}
console.log(obj.age); //26
obj.age = 100; //您不能修改年龄为100岁!!!
console.log(obj.age); //26

六、什么是方法

方法是能够在对象上执行的动作。说白了就是包含在对象中的函数

七、怎么定义对象方法

暂且不表

八、如何调用对象的方法?

1
objectName.methodName()

九、对象标签

对象级别的标签主要有三种:[[proto]]、[[class]]、[[extensible]]
1、原型链是通过proto这个标签来实现的
2、class表示对象是哪一个类型,没有直接的方式去查看或修改它;需要通过间接的手段;
3、extensible表示对象是否可扩展

十、对象序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
*后端需要一个字符串格式的数据
*/
var obj = {name:"wyang",age:26, hobby:["programme","eat"],gf:null,single:true};
JSON.stringify(obj); //"{"name":"wyang","age":26, "hobby":["programme","eat"],"gf":null,"single":true}"

/**
*坑:
*1. 如果序列化的值是'undefined',那么就不会出现在序列化的结果当中
*2. 如果序列化的值是'NaN'、'Infinity',那么会转换为'null'
*3. 如果序列化的值是时间的话,会转换成UTC的时间格式
*/
var obj = {name:'wyang',age:26, hobby:['programme','eat'],gf:null,single:true,love:undefined,a:NaN,b:Infinity,c:new Date()};
JSON.stringify(obj); //"{"name":"wyang","age":26, "hobby":["programme","eat"],"gf":null,"single":true,"a":null,"b":null,"c":"Mon Nov 02 2015 11:39:51 GMT+0800 (中国标准时间)"}"

/**
*后端返回一个json格式的数据,变为js对象
*/
var obj = JOSN.parse('{"name":"wyang"}');
obj.name //wyang;