一、面向对象简介
面向对象:通过将特征和行为封装起来,便于后续的重复调用。
对象的作用是:封装信息。比如Student类里可以封装学生的姓名、年龄、成绩等。
对象具有特征(属性)和行为(方法)。
面向对象:可以创建自定义的类型,很好的支持继承和多态。
面向对象的特征:封装、继承、多态。
基本数据类型和引用数据类型的对比
- 基本数据类型(值类型):String 字符串、Number 数值、Boolean 布尔值、Null 空值、Undefined 未定义。
- 引用数据类型(引用类型):Object 对象。
基本数据类型:
基本数据类型的值直接保存在栈内存中,值与值之间是独立存在,修改一个变量不会影响其他的变量。
对象:
只要不是那五种基本数据类型,就全都是对象。
如果使用基本数据类型的数据,我们所创建的变量都是独立,不能成为一个整体。
对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性。
对象是保存到堆内存中的,每创建一个新的对象,就会在堆内存中开辟出一个新的空间。变量保存的是对象的内存地址(对象的引用)。
换而言之,对象的值是保存在堆内存中的,而对象的引用(即变量)是保存在栈内存中的。
如果两个变量保存的是同一个对象引用,当一个通过一个变量修改属性时,另一个也会受到影响。
二、对象的分类
1.内置对象:
- 由ES标准中定义的对象,在任何的ES的实现中都可以使用
- 比如:Math、String、Number、Boolean、Function、Object…
2.宿主对象:
- 由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象。
- 比如 BOM DOM。比如
console
、document
。
3.自定义对象:
- 由开发人员自己创建的对象
三、对象的基本操作
1、创建对象
使用new关键字调用的函数,是构造函数constructor。构造函数是专门用来创建对象的函数。
例如:
var obj = new Object();
另外,使用typeof
检查一个对象时,会返回object
。
方法一:对象字面量
对象的字面量就是一个大括号{},里面的属性和方法均是键值对,即key和value。
var obj = {
属性名:属性值;
.....
};
使用对象字面量,可以在创建对象时,直接指定对象中的属性。语法:{属性名:属性值,属性名:属性值…}
对象字面量的属性名可以加引号也可以不加,建议不加。如果要使用一些特殊的名字,则必须加引号。
属性名和属性值是一组一组的键值对结构,键和值之间使用:
连接,多个值对之间使用,
隔开。如果一个属性之后没有其他的属性了,就不要写,
,因为它是对象的最后一个属性。
例如:
var student = {
name: "小米", //注意这里属性后面是用逗号隔开
age: 18,
hobby: function(){
console.log(this.name + "喜欢rap");
}
}
console.log(student); //输出结果为小米喜欢rap
方法二:工厂模式
**优势:**可以大批量的创建的创建对象。
**劣势:**使用工厂模式创建的对象,使用的构造函数都是object。多以创建的对象都是object类型,就会导致我们无法区分出不同类型的对象。
function student(name,age,gender){
var obj = new Object(); //创建了新的对象
obj.name = name; //向对象中添加属性
obj.age = age;
obj.gender = gender;
obj.grade = function(){
console.log(this.name + "是二班的");
};
return obj; //返回对象
}
var student1 = student("小米",12,"女"); //调用函数
var student2 = student("大米",13,"男");
方法三:利用构造函数
function Student(name){
this.name = name; //this指的是构造函数中的对象实例
this.grade = function(){
console.log(this.name + "是二班的");
}
}
var student1 = new Student("小米"); //自定义对象
var student2 = new Student("大米");
(具体什么是构造函数在第五部分由解释)
方法四:class创建对象(ES6新出的规范,允许class创建对象)
class Cat{
/定义构造函数
constructor(name,color){
this.name = name;
this.color = color;
/*this.like = function(){
console.log(this.name + "喜欢" + this.color);*/
}
like(){
console.log(this.name + "喜欢" + this.color);
}
}
var c1 = new Cat("点点","棕色");
var c2 = new Cat("甜甜","白色");
console.log(c1);
console.log(c2);
(类和实例具体解释在第六部分出现)
2、向对象中添加属性
在对象中保存的值称为属性。
向对象添加属性的语法:
对象.属性名 = 属性值;
举例:
var obj = new Object();
//向obj中添加一个name属性
obj.name = "易烊千玺";
//向obj中添加一个gender属性
obj.gender = "男";
//向obj中添加一个age属性
obj.age = 18;
console.log(JSON.stringify(obj)); // 将 obj 以字符串的形式打印出来
打印结果:
{
"name":"易烊千玺",
"gender":"男",
"age":18
}
补充1:对象的属性值可以是任何的数据类型,也可以是个函数:(也称之为方法)
var obj = new Object();
obj.sayHello = function () {
console.log("hello");
};
console.log(obj.sayHello); //没加括号,获取的是对象
console.log('-----------');
console.log(obj.sayHello()); //加了括号,执行函数体的内容
补充2:js中的属性值,也可以是一个对象。
举例:
//创建对象 obj1
var obj1 = new Object();
obj1.test = undefined;
//创建对象 obj2
var obj2 = new Object();
obj2.name = "易烊千玺";
//将整个 obj2 对象,设置为 obj1 的属性
obj1.test = obj2;
console.log(obj1.test.name); //输出结果为易烊千玺
3、获取对象中的属性
方式1:
语法:
对象.属性名
如果获取对象中没有的属性,不会报错而是返回undefined
。
举例:
var obj = new Object();
//向obj中添加一个name属性
obj.name = "易烊千玺";
//向obj中添加一个gender属性
obj.gender = "男";
//向obj中添加一个age属性
obj.age = 18;
// 获取对象中的属性
console.log(obj.gender); // 输出结果:男
console.log(obj.color); // 输出结果:undefined
方式2:可以使用[]
这种形式去操作属性
对象的属性名不强制要求遵守标识符的规范,但是我们使用是还是尽量按照标识符的规范去做。
但如果要使用特殊的属性名,就不能采用.
的方式来操作对象的属性。比如说,123
这种属性名,如果我们直接写成obj.123 = 789
,是会报错的。那怎么办呢?办法如下:
语法格式如下:(读取时,也是采用这种方式)
对象["属性名"] = 属性值
上面这种语法格式,举例如下:
obj["123"] = 789;
重要:使用[]
这种形式去操作属性,更加的灵活,因为,我们可以在[]
中直接传递一个变量,这样变量值是多少就会读取那个属性。
4、修改对象的属性值
语法:
对象.属性名 = 新值
对象[属性名] = 新值
obj.name = "tom";
obj['name'] = 'tom';
5、删除对象的属性
语法:
delete obj.name;
delete obj['name']
6、in 运算符
通过该运算符可以检查一个对象中是否含有指定的属性。如果有则返回true,没有则返回false。
语法:
"属性名" in 对象
对象.hasOwnProperty('属性名')
举例:
//检查obj中是否含有name属性
console.log("name" in obj);
console.log(obj.hasOwnProperty('name'))
我们平时使用的对象不一定是自己创建的,可能是别人提供的,这个时候,in 运算符可以派上用场。
7、遍历对象中的属性:for in
语法:
for (var 变量 in 对象) {
}
解释:对象中有几个属性,循环体就会执行几次。每次执行时,会将对象中的每个属性的 属性名 赋值给变量。
举例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
var obj = {
name: "易烊千玺",
age: 18,
gender: "男",
};
//枚举对象中的属性
for (var n in obj) {
console.log("属性名:" + n);
console.log("属性值:" + obj[n]); // 注意,因为这里的属性名 n 是变量,所以,如果想获取属性值,不能写成 obj.n,而是要写成 obj[n]
}
</script>
</head>
<body>
</body>
</html>
四、栈内存和堆内存
我们首先记住一句话:JS中,所有的变量都是保存在栈内存中的。
然后来看看下面的区别。
基本数据类型:
基本数据类型的值,直接保存在栈内存中。值与值之间是独立存在,修改一个变量不会影响其他的变量。
引用数据类型:
对象是保存到堆内存中的。每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而变量保存了对象的内存地址(对象的引用)。如果两个变量保存了同一个对象的引用,当一个通过一个变量修改属性时,另一个也会受到影响。
五、构造函数
构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写。
构造函数和普通函数的区别就是调用方式的不同:普通函数是直接调用,而构造函数需要使用new关键字来调用。
// 创建一个构造函数,专门用来创建Person对象
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.sayName = function() {
alert(this.name);
};
}
var per = new Person("易烊千玺", 20, "男");
var per2 = new Person("周震南", 18, "男");
var per3 = new Person("华晨宇", 30, "男");
this的指向也有所不同:
- 1.以函数的形式调用时,this永远都是window。比如
fun();
相当于window.fun();
- 2.以方法的形式调用时,this是调用方法的那个对象
- 3.以构造函数的形式调用时,this是新创建的那个对象
new一个构造函数的执行流程:
(1)开辟内存空间,存储新创建的对象
(2)将新建的对象设置为构造函数中的this,在构造函数中可以使用this来引用 新建的对象
(3)执行函数中的代码(包括设置对象属性和方法等)
(4)将新建的对象作为返回值返回
// 创建一个函数
function createStudent(name) {
var student = new Object();
student.name = name; //第一个name指的是student对象定义的变量。第二个name指的是createStudent函数的参数。二者不一样
}
改写为:
// 创建一个函数
function Student(name) {
this.name = name; //this指的是构造函数中的对象实例
}
六、类和实例
使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类。
通过一个构造函数创建的对象,称为该类的实例。
instanceof
使用 instanceof 可以检查一个对象是否为一个类的实例。
语法如下:
对象 instanceof 构造函数
如果是,则返回true;否则返回false。
function Person() {}
function Dog() {}
var person1 = new Person();
var dog1 = new Dog();
console.log(person1 instanceof Person); // 输出结果: true
console.log(dog1 instanceof Person); // 输出结果:false
console.log(dog1 instanceof Object); // 所有的对象都是Object的后代。因此,输出结果为:true
所有的对象都是Object的后代,因此 任何对象 instanceof Object 的返回结果都是true。
七、json的介绍
JSON:JavaScript Object Notation(JavaScript对象表示形式)。
JSON和对象字面量的区别:JSON的属性必须用双引号引号引起来,对象字面量可以省略。
{
"name" : "zs",
"age" : 18,
"sex" : true,
"sayHi" : function() {
console.log(this.name);
}
};
注:
1)json里一般放常量、数组、对象等,但很少放function。
2)对象和json没有长度,json.length的打印结果是undefined。于是乎,自然也就不能用for循环遍历(因为遍历时需要获取长度length)。
json遍历的方法:
json 采用 for...in...
进行遍历,和数组的遍历方式不同。如下: