1.基本数据类型和引用数据类型(p49)
引用数据类型即为对象
-
基本数据类型都是单一的值“hello” 123 true,
值和值之间没有任何联系 -
在js中来表示一个人的信息(name gender age)
如果用基本数据类型,我们所创建的变量都是独立的,不能成为一个整体
如果使用对象就方便的多 -
基本数据类型
String Number Boolean Null Undefined -
引用数据类型
Object -
JS中的变量都是保存到栈内存中的
基本数据类型的值直接在栈内存中存储
值与值之前是独立存在,修改一个变量不会影响其他的变量
对象是保存在堆内存中的,没创建一个新的对象,就会在堆内存中开辟出一个新的空间
而变量保存的是对象的内存地址(对象的引用)
如果两个变量保存的是同一个对象引用,那么当通过一个变量修改属性时,另一个也会受到影响(他们不是独立的)
当比较两个基本数据类型的值时,就是比较值
而比较两个引用数据类型时,它是比较对象的内存地址
如果两个对象是一模一样的,但是地址不同他也会返回false
2.基本数据类型的包装类(P83)
在JS中为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转化为对象
String()
Number()
Boolean()
var num = new Number(3);
var str = new String("hello");
var bool = new Boolean(true);
-
在实际应用中不会使用包装类
如果使用包装类,在做一些值的比较时可能会带来一些不可预期的结果 -
方法和属性只能添加给对对象,不能添加给基本数据类型
当我们对一些基本数据类型的值调用属性和方法时,浏览器会临时使用包装类将其转换为对象,然后再调用对象的属性和方法类似于java的自动装箱和拆箱
var s = 123;
s= s.toString();
console.log(s);
3.对象
对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性
对象的分类
-
内建对象
有ES标准中定义的对象,在任何的ES的实现中都可以使用
比如Math String Number Boolean Function Object -
宿主对象
由js的运行环境提供的对象,目前来将主要是指由浏览器提供的对象
比如
BOM:浏览器对象模型
DOM:文档对象模型 -
自定义对象
由开发人员自己创建的对象
对象的基本操作
- 创建对象
//使用new关键字调用的函数,是构造函数constructor
//构造函数是专门用来创建对象的函数
使用typeof检查一个对象时会返回object
var obj = new Object();
- 向对象添加属性和读取
在对象中保存的值称为属性
向对象添加属性
语法
对象.属性名=属性值
var obj = new Object();
obj.name="孙悟空";
obj.gender = "男";
//读取
console.log(obj.name);
如果读取对象中没有的属性,不会报错而是会返回undefined
- 修改对象的属性值
和java不一样
语法:对象.属性名=新值
对象的属性名和属性值
属性名
-
对象的属性名不强制要求遵守标识符的规范
什么乱七八糟的名字都可以使用 -
但是我们使用时还是尽量按照标识符的规范去做
-
注
如果要使用特殊的属性名,不能采用"."的方式来操作
需要使用另一种方式:
语法:对象名["对象名"]=属性值
obj.123 = 789;×
obj["123"]=789;√
读取时也要采用这种方式
console .log(obj["123"]);
使用[]这种形式去操作属性,更加灵活,
在[]中可以直接传递一个变量,这样变量值是多少就会读取那个属性
obj["123"]=789;
obj["nihao"]="你好";
var n = "nihao";
console.log(obj[n]);
好处就是,可以随意改变变量n的值输出对象的不同属性
- in运算符
通过该运算符可以检查一个对象中是否含有指定的属性
如果有则返回true,没有则返回false
语法:"属性名" in 对象
//检查obj中是否含有test2属性
console.log("test2" in obj);
对象字面量
-
原来创建一个对象
var obj = new Object();
-
使用对象字面量来创建一个对象
var obj = {};
使用对象字面量,可以在创建对象时,直接指定对象中的属性
语法:{属性名:属性值,属性名:属性值。。。。}
var obj2 = {name:"猪八戒",age:28,gender:"男"};
属性名和属性值是一组一组的名值对结构
名和值之间使用“:”连接,多个名值之间使用“,”隔开
如果一个属性之后没有其他属性了。就不要写
使用工厂方法创建对象(P63)
通过该方法可以大批量的创建对象
fucntion createPerson(){
var obj = new Object();
//将新的对象返回
return obj;
}
使用构造函数创建对象(P64)
构造函数就是一个普通的函数,创建方式和普通函数没有区别
不同的是构造函数习惯上首字母大写
function Person(){
this.name="tom";
this.age=18;
this.gender="man";
//对象中添加一个方法
this.sayName = fucntion(){
alert("Hello大家好,我是:"+this.name);
};
}
var per = new Person();
- 构造函数和普通函数的区别就是调用方式的不同
普通函数是直接调用,而构造函数需要使用new关键字来调用
构造函数的执行流程
1.立即创建一个新的对象
2.将新建的对象设置为函数中的this,在构造函数中可以使用this来引用新建的对象
3.逐行执行函数中的代码
4.将新的对象作为返回值
使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类。
我们将通过一个构造函数创建的对象,称为是该类的实例
- 使用instanceof可以检查一个对象是否是一类的实例,返回为boolean
语法:
对象 instanceof 构造函数
如果是,则返回true,否则返回false
对于构造方法的总结
创建一个Person构造函数
- 在Person构造函数中,为每一个对象都添加了一个sayName方法
目前我们的方法是在构造函数内部创建的,也就是构造函数每执行一次就会创建一个新的sayName方法,所有的实例的sayName都是唯一的。
这就导致了构造函数执行一次就会创建一个新的方法,执行1w次就会创建1w个方法,而这1w个方法都是一模一样的
这是完全没有必要的,完全可以使所有的对象共享一个方法
原型对象(P66)
将函数定义在全局作用域,污染了全局作用于的命名空间
而且定义在全局作用域中也很不安全,(容易引起命名冲突)
原型prototype(类似于java的静态变量)
我们所创建的每一个函数,解析器都会想函数中添加一个属性prototype
- 这个属性对应着一个对象,这个对象就是我们所谓的原型对象
如果函数作为普通函数调用prototype没有任何作用,
当函数通过构造函数调用时,它所创建的对象中都会有一个隐含的属性指向该构造函数的原型对象,我们可以通过proto来访问该属性
mc.__proto__ 和MyClass.prototype一样,用于查看原型对象
-
创建的所有对象都指向这个原型对象
-
原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象
我们可以将对象中共有的内容,统一设置到原型对象中
MyClass.prototype.a = 123;//MyClass()为构造函数
当我们访问对象的一个属性或方法是,他会现在对象自身中寻找,如果有就直接使用,
如果没有则会去原型对象中寻找,如果找到则直接使用
以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,
这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每一个对象都具有这些属性和方法了
- 使用 in 检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true
可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性
console.log(mc.hasOwnProperty("hasOwnProperty"));
console.log(mc.__proto__.hasOwnProperty("hasOwnProperty"));//false
console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));//true
原型对象也是对象,所以它也有原型
当我们使用一个对象的属性或方法是,会在自身中寻找
自身对象中如果有,则直接使用,如果没有则去原型对象中寻找,如果原型对象中有,则使用
如果没有则去原型的原型中寻找,直到找到Object对象的原型
Object没有原型,如果在Object中依然没有找到,则返回undefined
this总结:
- 当以函数的形式调用时,this是window
- 当以方法的形式调用时,谁调用方法this就是谁
- 当以构造函数的形式调用时,this就是新创建的那个对象
3.toString()
是Object中的方法,和java中一样
fucntion Person(name,age,gender){
this.name = name;
this.age = age;
this.gender = gender;
}
Person.prototype.toString = function(){
return "Person[name="+this.name+"age="+this,age+"gender="+this.gender+"]";
};
//创建一个Person实例
var per = new Person("孙悟空",18,“男”);
4.垃圾回收
当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象
此时该对象就是一个垃圾,这种对象过多就会占用大量的内存空间,导致程序运行变慢
- 在js中拥有自动的垃圾回收机制,会自动将这些垃圾对象存内存中销毁
我们不需要也不能进行垃圾回收的操作 - 我们需要做的只是要将不再使用的对象设置null即可