前面的话:
说到对象,我首先想到的是每到过年过节见长辈的时候长辈们老是开玩笑的问我“你找了对象没?”。不说大家都知道,这里的“对象”指的是“女朋友”,但是今天我想要说的js中的“对象”和我们生活中谈到的“对象”不是同一回事,但是其中也有着很多相似之处。
在讲js中的对象之前,我想先抛出几个疑问:
什么是对象?
对象有哪些?
对象能做什么?
如何创建对象?
如何对对象进行操作?
对象有特性么?有的话有哪些特性?
对象有属性么?有的话有哪些?对属性如何操作?
……
什么是javascript中的对象?
在ECMA-262中把对象定义为:“无序属性的集合,其属性可以包含基本值、对象、或者函数。”严格来说,这就是相当于说对象是一组没有特定序列的值。对象的每一个属性或方法都有一个名字,而每一个名字都映射到一个值。(如:“女朋友”[对象]喜欢运动[对象的属性或方法]–打篮球[属性对应的值],我门可以试着这样去理解,但实际可能有所区别)
在经典的面向对象语言中,对象是指数据和在这些数据上进行的操作的集合。与 C++ 和 Java 不同,JavaScript 是一种基于原型的编程语言,并没有 class 语句,而是把函数用作类。
我理解的javascript对象:
第一:Javascript对象是 基本数据类型 之一,是复合类型;
第二:Javascript中 几乎所有事物都是做对象 ;
第三:Javascript的对象是 拥有属性和方法 的 数据 ;
第四:JavaScript 中的对象可以简单理解成 “名称:值”对 (name:value)。名称(name):”名称”部分是一个 JavaScript 字符串
在javascript语句中这三种形式是一样的
var obj={prop:1}
var obj={"prop":1}
var obj={'prop':1}
在这里看起来属性名既可以加引号也可以不加引号,但是在实际中有这么几种情况你必须将属性名放到引号中间
如果属性名是Javascript的保留字之一
如果属性名种包含特殊字符(除字母、数字、下划线以外的字符)
如果属性名以数字开头
在ECMAScript5中,保留字可以用作不带引号的属性名,但对于ECMAScript3中必须用引号括起来
在ECMAScript5中对象直接量中的最后一个属性后的逗号将被忽略,在ECMAScript 3的大部分实现中也可以忽略这个逗号,但在IE中报错
值(value):”值”部分可以是任何 JavaScript 的数据类型——包括对象
对象有哪些呢?
学过java的都知道,在java中有一句很经典的描述对象的话“万物皆对象”,是的,在javascript中也是一样。在javascript中我们可以把对象分为两大类,一类是内建对象(数据封装对象,工具类对象,错误对象,后面会有专门针对内建对象的博客),一类是自定义对象(这篇文章里面讲的主要就是自定义对象)
对象能做什么?
在这里我要先卖个关子,到后面的时候告诉大家。
如何创建对象?
既然了解了对象和基本的对象分类,我们是否应该要知道如何去创建一个自定义的对象呢?
1、通过对象字面量的方式创建对象 (对象字面量是一个表达式,这个表达式的每次运算都创建并初始化一个新对象。每次计算对象字面量的时候,也都会计算他的每个属性的值。也就是说,如果在一个重复调用的函数中的循环体内使用了对象直接量,它将创建很多新对象,并且每次创建的对象的属性值也有可能不同。)
语法:var obj = {};
实例:
首先,我们创建一个空的对象,里面没有任何属性,我们来获取它的类型
var obj1 = {};//没有任何属性的对象
console.log(typeof obj); //object
它返回的结果是object,说明我们创建的是一个object对象,当然,我们还可以用下面的方法来创建
var obj2={x:1,y:2,z:3};
var obj3={
'x':1,
"y":2,
username:'king',
'for':'javascript关键字必须放到引号中间', //for是javascript关键字,必须放到引号中间
'first-name':'foodoir', //-是特殊字符,也需要放在引号中间
married:true,
test:null,
test1:undefined,
salary:12.3,
person:{ //在对象中"值"部分可以是任何 JavaScript的数据类型——包括对象
username:'king',
age:21,
addr:'北京',
}, //最后一个对象属性的后面的逗号可以写可以不写,在ECMAScript 5中自动被忽略,在ECMAScript 3的大部分实现中也可以忽略这个逗号,但在IE中报错
}
2、通过new object创建对象
语法:var obj = new Object();
实例:
var obj4 = new Object();//创建一个空对象
var arr = new Array();//创建一个空数组对象
var date = new Date();//创建一个空时间对象
3、通过构造函数的形式创建对象
语法:function Person(){};或者var Person=function(){};
实例:
var obj5=new Test1();
function Test1(num1,num2){
this.n1=num1;
this.n2=num2;
}
var obj6=new Test1(5,6);
console.log(typeof obj6); //object
console.log(obj6 instanceof Object); //true
在使用通过构造函数的形式创建对象时应注意:
a.使用的时候通过new操作符得到对象var person1=new Person()
b.用构造器创建对象的时候可以接收参数
c.构造器函数的首字母最好大写,区别其他的一般函数
注意:构造器属性(constructor property),当我们创建对象的时候,实际上同时也赋予了该对象一种特殊的属性,就是构造器属性,这个构造器属性实际上是一个指向用于创建该对象的构造器函数的引用
补充:
typeof 和 instanceof 常用来判断一个变量是否为空,或者是什么类型的。但它们之间还是有区别的:
typeof 是一个一元运算,放在一个运算数之前,运算数可以是任意类型。
它返回值是一个字符串,该字符串说明运算数的类型。typeof 一般只能返回这几个结果:number,boolean,string,function,object,undefined。
我们可以使用 typeof 来获取一个变量是否存在,如 if(typeof a!=”undefined”){alert(“ok”)},而不要去使用 if(a) 因为如果 a 不存在(未声明)则会出错,对于 Array,Null 等特殊对象使用 typeof 一律返回 object,这正是 typeof 的局限性。
instanceof 用于判断一个变量是否某个对象的实例
在上面的例子中,obj6 instanceof Object判断的为true,则说明创建的obj6也是Object类型
4、通过Object.create()创建对象
var obj7 = Object.create({x:1});
//创建一个普通的空对象
var obj8 = Object.create(null);
//创建一个对象的原型属性
var obj9 = Object.create(Object.prototype); //prototype对象的原型属性
console.log(typeof obj7); //object
console.log(typeof obj8); //object
console.log(typeof obj9); //object
//通过instanceof 操作符检测对象是否由某个指定的构造器函数创建的
console.log(obj7 instanceof Object); //true
console.log(obj8 instanceof Object); //false,注意:空对象用instanceof判断时,结果为false
console.log(obj9 instanceof Object); //true
如何对对象进行操作?
学过数据库的我们都知道,数据库最基本的四个操作分别是“增、删、查、改”,那么在对对象的操作中是否也存在类似的操做呢?是的,在对对象的操作中也有查询,添加,修改,删除操作,都是基于对象的属性的操作。下面我们来介绍对象的几个基本操作。
首先,我们先要通过查询方法,来获取对象中的属性,访问属性有三种方法:对象名.属性名;对象名[属性名];当处于某个对象方法内部的时候,可以通过this来访问同一对象的属性
var person = {
username: "foodoir",
age: 21,
sex: "男",
addr: "湖南",
salary: 123456,
};
console.log("姓名:" + person.username + "\n" + "性别:" + person.sex); //姓名:foodoir 性别:男
console.log("年龄:" + person['age'] + "\n" + "薪水:" + person["salary"]); //年龄:21 薪水:123456
//如果属性不确定,需要使用[]
var key = 'username';
console.log(person.key); //undefined 此种方法不能得到key的值,通过[]方法可以得到
console.log(person[key]); //foodoir 当属性不确定时,用该方法
console.log(person['key']); //undefined
看到这里,你肯定会有有疑问,为什么第9行代码中person[‘age’]中的age和person[“salary”]中的salary都加了引号,且都可以显示出结果,而在第13行代码中person[‘key’]中的key加了引号,反而返回值是undefined 原因究竟是什么呢?
age为person对象中的属性名,而该对象只对person进行了定义,没对person里面的属性进行定义,故在调用的时候,在[]中间应该加上引号,也就是说,person[‘age’]和person.age是等价的
而key是在对象外定义的(var key = ‘username’;),在对象里面它是不存在key这个属性的(即属性不确定),此时直接用person[key]方法就好了,person.key和person[‘key’]返回的必须是person对象里面确定的属性,key没在person属性里面,故这两种方法返回的值都是undefined
学会了如何 获取对象的属性 ,然后我们该继续学习对象中的属性进行添加,修改和查询操作
function personInfo(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
var person1 = new personInfo('foodoir', 20, '男');
console.log(person1.name + person1.sex); //foodoir男
属性的添加 有两种方式:对象名.属性名=值;对象名[属性名]=值
//添加属性
var obj = {};
obj.username = 'foodoir';
obj.age = 21;
obj.sex = '男';
obj.addr = '湖南';
obj['test'] = 'hello world';
console.log(obj.username + " " + obj.age + " " + obj.sex + " " + obj.addr + " " + obj['test']); //foodoir 21 男 湖南 hello world
属性的修改 也有两种方式:对象名.属性名=值;对象名[属性名]=值
//修改指定属性
obj.username = 'chenwu';
console.log("修改之后的名字:" + obj.username); //修改之后的名字:chenwu
obj['test'] = 'hello javascript';
console.log("修改之后的test:" + obj['test']); //修改之后的test:hello javascript
属性的删除 也有两种方式:delete 对象名.属性名;delete 对象名[属性名] 。在delete删除指定的属性时应该注意:(后面讲对象的结构的时候会详细介绍)
delete只能删除自身属性,不能删除继承属性
要删除继承属性,只能从定义它属性的原型对象上删除它,而且这会影响到所有继承自这个原型的对象
delete只是断开属性和宿主对象的联系,而不会去操作属性的属性
delete不能删除哪些可配制性为false的属性
//通过delete删除指定的属性
delete obj.sex;
console.log(obj.sex); //undefined
delete obj['test'];
console.log(obj['test']); //undefined
除了“增、删、改、查”我们还要学会对象中的遍历,对象中的遍历有两种, 一种是for/in遍历 , 一种是通过Object.keys(obj)函数进行遍历
var obj = {
x: 1,
y: 2,
test: "helloworld",
edu: "javascript",
};
//通过for/in遍历属性
for(var i in obj) {
console.log(i); //x y test edu(换行输出)
console.log(obj[i]); //输出的是属性名对应的属性值
}
//通过Object.keys(obj)遍历属性
console.log(Object.keys(obj)); //["x", "y", "test", "edu"]