一、对象的概念
对象: 无序的名值对 的集合 (键值对 的集合)
在JS当中,可以说一切皆对象:
-
如果存储一个简单的数据(一个数字,一个字符串)直接var a = 10。 -
如果存储一堆的数据,此时我们想到数组,数组就是专门用来存储多个数据用的。 -
如果我们想要执行一段代码,或者让这段代码有功能,此时我们需要函数。 -
如果我想描述一个复杂的事物,比如说一个人、一台电脑(需要用到多个属性或者方法才能描述清楚),此时就要用到对象。
二、对象的创建方法
一般我们说的对象都是Object的实例对象(万能,通用的,可以表示任何事物的)
1.字面量创建(常用)
var obj = {};
我们来创建一个手机对象:
var obj = {
name:'iphoneX',
color:'black',
call:function()
{
console.log('打电话');
}
}
console.log(obj);
它的结果如下图所示:
我们来调用对象obj 的call 方法:
obj.call();
成功输出“打电话”。
**注意:**属性之间用逗号 分隔,不能用分号。
2.构造函数定义(new Object)
var obj = new Object();
如上述代码所示,就是使用构造函数的方法定义了一个对象。
需要注意的是:
- 如果带了
new ,证明在把这个函数当做构造函数 来用。 - 如果不带
new ,证明在把这个函数当做普通函数 来用。
举个例子:
var obj1 = new Object();
var obj2 = new Object({name:'杨幂',age:18});
console.log(obj2);
var obj3 = {
name:'杨幂',
age:18
}
console.log(obj3);
3.工厂函数定义(本质上还是使用构造函数)(几乎不用)
function createObject(name,age)
{
var obj = new Object();
obj.name = name;
obj.age = age;
return obj;
}
console.log(createObject('热巴',18));
三、对象的操作(增删改查)及遍历
字面量定义对象与构造函数定义对象其实是一回事
我们来定义一个对象obj,后续操作都是对它进行操作。
var obj = {};
1.增
直接增加属性:
obj.name = '小黄';
obj.age = 1;
console.log(obj);
我们说对象里面就是一个个名值对 ,类似于Python中的字典 。所以操作属性还有另外一种方法:
obj["color"] = 'yellow';
obj["category"] = '阿拉斯加';
如果用的是上面这种[ ] 的方式,那么[ ] 当中加引号 是在往对象 当中添加名 或者键 (名值对也叫键值对)。
如果不加[ ] ,则[ ] 当中的内容就会被当作变量 处理,没有定义过这个变量 就会报错。
举个例子:
var obj = {};
var cry = 'call';
obj[cry] = function()
{
console.log('汪');
}
2.改
改的操作与增 的操作一样,不过它遵循的是“无则增加,有则更改”的原则。
obj.color = 'black';
obj["name"] = '小黑';
var a = 'category';
obj[a] = '金毛';
3.查
查的操作,直接写即可,有则查找成功,无则undefined 。
console.log(obj.name);
console.log(obj["color"]);
var a = 'category';
console.log(obj[a]);
console.log(obj.haha);
4.删
删的操作简单粗暴,使用delete 关键字就可以搞定。
delete obj.category;
delete obj["color"];
var a = 'age';
delete obj[a];
5.遍历
遍历也算是查操作,查对象当中所有的属性。
注意: 遍历数组用for ,遍历对象 用for in 。
定义一个对象:
var obj =
{
name:'car',
category:'劳斯莱斯',
color:'hotpink',
money:10000000,
run:function()
{
console.log('跑的很快!');
}
}
使用for in 进行遍历:
for(var key in obj)
{
console.log(key,obj[key]);
}
注意点:
- 如果是在
遍历对象 的时候,取值只能使用[ ] 的方式,因为key 是一个变量 。 - 如果写成
obj.key ,则拿到的会是undefined ,因为这样写,key 会被认为是对象里面的属性 。 obj[key] ,key 被解析为变量 ,使用变量的值 进行替换。
思考
我们平时使用的输出语句console.log() 与上面例子中的obj.run() 为何两者如此相似?答案——console也是一个对象 。
验证:
console.log(console)
结果:
四、构造函数创建特定实例对象
1.构造函数的基本概念
构造函数
构造函数本质上也是一个函数 ,只不过通常我们把构造函数 的名字写成大驼峰 。在ES5 版本的JS 当中,没有类 的概念,构造函数 可以理解为类 。
在Python 中,对象 是由类 实例化生成的,所以JS 这里可以将构造函数 当成类 来看(可以把类 理解为生对象 的模子 )。如果我创建一个构造函数 叫做Person ,这个模子 就定好了,它就只能产生人 对象,不可能产生一条狗 对象出来。构造函数 是为了让我们更方便的创建多个 具有相同特征 的对象 。
构造函数 用法和普通的函数 用法是一样的,直接可以调用 ,只不过它比普通函数多了一种用法—— new 。
案例
定义一个“人” 的构造函数 ,所以这个构造函数是产生人 这个对象 的模子 。
function Person(name,age,gender)
{
this.name = name;
this.age = age;
this.gender = gender;
this.eat = function()
{
console.log('吃饭');
}
console.log(this);
}
this是个啥?
通常情况下在任何函数 当中都会有this 这个关键字。
this 代表着调用这个函数 或者方法 的那个对象 (注意是对象 ),这个函数或者说这个方法这个时候是谁的,this 的结果就是谁。如果函数是在全局 环境,那么结果就是window ,将在下面(2.window对象) 中进行讲解。
注意: this 指向谁得分情况进行考虑,将在下面(3.对this的讲解) 中进行讲解。
我们先把这个构造函数当做普通函数 调用:
var a = Person('zs',23,'2');
console.log(result);
我们来看看此时函数Person 中“console.log(this)” 的结果:
name属性在最下面,不便截图查看,它也存在于window对象中。
我们现在把这个函数当做构造函数 调用生成对象 (加new)。
调用构造函数 加了个new ,就是在实例化对象 。就相当于让Person 这个妈妈 赶紧生一个对象(孩子) ,让它生对象的时候给它传 生出来的娃叫啥(name) ,年龄多大(age) ,是男是女(gender) 。而且当加了new 以后,它的返回值 就是实例化 出来的那个对象 。
var per1 = new Person('zs','23','male');
console.log(per1);
让我们来看看此时函数内“console.log(this)” 与外部“console.log(per1)” 的结果:
两者结果一模一样,this 此时就是per1 对象。
什么点什么 ,前边的东西肯定是对象 ,对象点什么 ,其实就是往对象 当中要么添加属性 要么更改属性 。
所以,调用构造函数 实例化对象时,其中的this.xx 就是往this 当前所指代的对象 当中添加或更改属性。
new关键字实例化对象的过程:
- 开辟内存空间
- this指向该内存
- 执行函数
- 生成实例对象并返回(虽然我们没有写返回值,但它相当于自动添加了
return this )
2.window对象(全局对象)
全局对象 ,全名为浏览器窗口对象 ,代码执行的时候所有的一切 ,都是包含在全局对象 下的。
我们在全局环境 下直接定义的函数 或者变量 ,都是全局对象 下的一个属性 。
所以我们一般将window对象 下的方法称为函数 ,其他对象 下的方法 就只称为方法 。
3.对this的讲解
通常情况下在任何函数当中都会有this这个关键字。
this 本质是一个对象 ,代表着调用这个函数或者方法的对象(这个函数的执行者) 。这个函数或者说这个方法是谁的,this 就代表谁。
this指向谁得分情况进行考虑,一般有以下四种情况:
-
this在函数 当中,函数也可以叫做是window对象的方法 ,this永远代表window ; var a = 10;
function add(a,b)
{
console.log(this);
return a + b;
}
console.log(window.add(10,20));
-
this在事件 当中,回调函数 当中的this ,代表的是事件对象 ; -
this在对象的方法 当中,this 代表的是这个对象 ; obj{
add:function()
{
console.log(this);
}
}
-
this在构造函数 当中,代表的是实例化出来的那个对象 ;
4.构造函数实例化对象过程及内存展现
案例:歌手
function Singer(name,gender,age)
{
this.name = name;
this.gender = gender;
this.age = age;
this.sing = function(){
console.log('我什么都能唱!');
}
}
我们来实例化出两个实力派歌手:
var singer1 = new Singer('邓紫棋','famale',28);
singer1.sing();
console.log(singer1.name);
console.log(singer1['age']);
var singer2 = new Singer('腾格尔','male',50);
singer2.sing();
console.log(singer2.name);
console.log(singer2['age']);
内存展现:
过程:
首先把全局环境 押入栈区,从上到下收集变量 (函数也属于变量)。
然后在堆区当中开辟内存,函数体放入内存当中,假设地址为100,将此地址绑定给Singer ,即让Singer 指向地址为100的内存空间 。
调用构造函数Singer 来实例化对象(new) ,我们知道new 的第一步就是开辟内存空间,假设第一个new 出来的空间内存地址为80 ,那么就会将此地址绑定给singer1 ,即让singer1 指向地址为80 的内存空间。此时this 也会指向内存地址为80 的内存空间,这也是new 的第二步。new 的第三步是执行函数体代码,给当前this 指向的内存空间中添加属性。因为singer1 绑定的是内存地址为80 的内存空间,所以函数体代码给内存空间中添加属性之后,这个空间 就是实例化出来的对象 。
所以我们说:this的指向随操作而变化,根本作用就是帮助操作空间。
|