JSON
- 什么是JSON:JSON是JavaScript Object Notation的缩写,它是一种数据格式。JSON的本质是一个字符串。
- JSON中的构成元素为:简单值、对象、数组
1)简单值:数值型、字符型、布尔型、Null,注意没有undefined
2)对象:用来存储无序的属性,注意对象不可以有名称,也不可以以分号作为结尾,没有函数
3) 数组:用来存储有序的数据,注意数组也不可以有名称,也不需要用分号作为结尾- 注意:
a.JSON中对象的键值对,键必须用双引号包起来
b.JSON中的字符串必须用双引号包起来- JSON数据的书写位置
1)可以写在独立的json文件中,文件的扩展名为.json
2) 将JSON写在JS文档中
{
"name": "Tom",
"age": 10,
"gender": "男",
"school": null,
"brothers": [
{
"name": "Jack",
"age": 13
},
{
"name": "Peter",
"age": 17
}
],
"hobby": ["爬山", "游泳"]
}
JSON字符串与JS对象的相互转化
- parse方法
1.作用:将JSON字符串转换为JS对象
2.格式:window.JSON.parse('JSON字符串');
- stringify方法
1.作用:将JS对象转换为JSON字符串
2.格式:JSON.stringify(JS对象);
var data='{"name":"jone","age":12,"gender":"男"}';
// 将JSON的字符串转换成JS对象
var obj=JSON.parse(data);
console.log(obj); //Object { name: "jone", age: 12, gender: "男" }
// 将JS对象转换成JSON字符串
var res=JSON.stringify(obj);
console.log(res); //{"name":"jone","age":12,"gender":"男"}
面向对象
- 面向过程:所谓面向过程就是指在完成某个需求之前,先分析完成该需求所需要经历步骤有哪些。然后按照步骤依次执行即可。面向过程重在过程。C语言就是典型的面向过程的语言
- 面向对象(英文简称OO):所谓面向对象就是指在完成某个需求之前,先分析出完成该需求所涉及的对象有哪些,然后再分析每个对象身上有哪些属性和方法,利用这些属性和方法完成响应的需求。Java、C++都是面向对象的语言,JS是一门基于对象的语言。
- 所谓对象就是指具有特定功能的无序的属性和方法的集合
创建对象的方法
1. 字变量形式
var obj = {
name: 'Tom',
age: 10,
gender: '男'
};
2. 构造方法
//构造方法定义格式
function 构造方法名称() {
this.属性名称 = 属性值;
this.属性名称 = 属性值;
this.属性名称 = 属性值;
this.方法名称 = function() {
// XXXXX
};
this.方法名称 = function() {
// XXXXX
}
}
// 构造方法的调用:
new 构造方法名称(实参,实参2,实参3...);
// 构造方法定义对象
function Student(name,age,gender){
this.name=name;
this.age=age;
this.gender=gender;
this.play= function () {
console.log("羽毛球");
}
}
var obj=new Student('张三',12,'男');
console.log(obj);
注:构造方法中的变量不属于任何对象
function Person(name, age) {
var salary = 1000;
this.name = name;
this.age = age;
this.getSalary = function() {
return salary;
}
}
var p = new Person('Tom', 10);
console.log(p.name); //Tom
console.log(p.age); //10
console.log(p.salary); //undefined
console.log(p.getSalary()); //1000
构造方法
1. 静态属性和静态方法
所谓静态属性和静态方法就是给构造方法直接绑定的属性和方法
// 静态属性和静态方法
function Person(name, age) {
this.name = name;
this.age = age;
}
// 静态属性
Person.a = 100;
// 静态方法
Person.fn = function() {
console.log('hello');
};
var p=new Person('Tom',12);
console.log(p.name); //Tom
console.log(p.a); //undefined
console.log(p.fn); //undefined
console.log(Person.a); //100
console.log(Person.fn); //function fn()
Person.fn(); //hello
2. 构造方法的执行顺序
构造方法在执行时的流程:
- 第一步:如果有形参,那么先将实参的数据传递给构造函数的形参,并且创建一个空对象,让this指向这个空对象(this一开始指向window)
- 第二步:执行构造函数中的语句,为空对象(this)绑定属性并且初始化
- 第三步:将创建好的对象返回给外部
3. 构造方法使用时的注意事项
1.构造方法的名称的首字母要大写,目的是和普通方法做区分
2.构造方法的名称代表了对象的类型
3.调用时必须加new
4.构造方法中为对象绑定的属性对象的私有属性,简单说,就是通过该构造方法创建对象时,每个对象身上都会有这么一份属性,而且这些属性是互不干扰的
4. 构造方法的不足
如果将所有的属性和功能都封装到构造方法中,那么当其属性值相同时,造成内存资源的浪费(因为构造方法里面的所有东西,会在创建对象时给每个对象身上绑定一份这样的属性)。
解决的方法就是将属性值相同的内容放到“公共空间”-----原型
5. 原型
- 什么是原型:每个函数中都会有一个属性——prototype属性,这个属性指向了一个对象,这个对象就被称为原型对象,简称原型。
- 原型中存储的是通过构造方法创建出来的所有对象可以共享的内容。
- 可以使用
构造方法名称.prototype
属性来获取原型对象- 原型对象的操作
1) 增
2) 删
3) 改
4) 查- this在原型中的使用:原型中的this代表调用原型内容的对象
- 为什么对象可以直接获取原型中的内容:
1)每个对象的内容会有一个__proto__属性,这个属性指向了创建该对象时的原型对象。
2)当利用对象去查找某个属性的时候,属性的查找顺序是:先从自身的私有属性中查找,如果私有属性中有要查找的属性,则返回其对应的值,如果私有属性中没有要查找的属性,则沿着__proto__的指向,到原型对象中查找。如果有则返回其对应的值。
3)如果私有属性和原型中的属性的名称相同,那么私有属性会将原型中的属性屏蔽掉
4)原型对象的获取
// 构造方法创建对象
function Student(name,age,gender){
this.Name=name;
this.age=age;
this.gender=gender;
this.play= function () {
console.log("羽毛球");
}
}
// 调用对象
var student=new Student('Tom',12,'男');
console.log(student);
// 为原型添加内容
Student.prototype.hobby= function () {
console.log("我喜欢打羽毛球");
};
Student.prototype.speak= function () {
console.log("我是"+this.Name); //this表示调用该原型的对象
};
Student.prototype.nation="中国";
Student.prototype.color='yellow';
// 更改原型内容
Student.prototype.nation="美国";
// 删除原型内容
delete Student.prototype.nation;
// 查找原型内容
Student.prototype.hobby();
res1=Student.prototype.color;
console.log(res1);
// 可以使用对象直接对原型内容进行获取
student.hobby();
student.speak(); //我是Tom
console.log(student.color);
6. 原型中的_proto_,prototype与constructor三个属性
1)每个对象的内容会有一个__proto__和constructor属性
2)prototype属性是函数独有的属性,而函数也是对象的一种,所以函数中有_proto_,prototype与constructor三个属性
3)实例化的对象中不含prototype属性,对象中的__proto__属性指向原型对象,找到对应的公有属性和公有方法
4)constructor属性指向该对象的构造函数
// _proto_跟constructor
function Person(Name){
this.Name=Name;
this.play= function () {
console.log("hello");
}
}
Person.prototype.age=12;
Person.prototype.speak= function () {
console.log("w");
};
var p=new Person('Tom');
console.log(p);
console.log(p.__proto__); //指向构造函数Person的原型对象
console.log(Person.__proto__); //指向构造函数Function的原型对象function()
console.log(p.prototype); //对象中没有prototype属性,故为undefined
console.log(Person.prototype); //指向构造函数Person的原型对象
console.log(p.constructor); //返回构造函数Person(name)
console.log(Person.constructor); //返回构造函数Function()
7. 判断属性是否属于某个对象
- instanceof操作符
a. 作用:判断某个引用类型的数据的具体类型
b. 格式:属性 instanceof 类型`
c. 结果:如果属于该类型,则返回true、否则为false- hasOwnProperty方法
a.作用:判断某个属性是否为对象的私有属性,如果是则返回true、否则返回false
b.格式:对象.hasOwnProperty('属性名称');
- in关键字
a.作用:判断对象是否有某个属性(不论是私有的,还是公有的),如果有返回true、否则返回false
b.格式为:'属性名称' in 对象名称;
function Person(Name,age){
this.Name=Name;
this.age=age;
}
var p1=new Person('Tom',12);
var p=new Student('jack',12);
// instanceof操作符
console.log(p1 instanceof Person); //true
console.log(p instanceof Person); //false
// hasOwnProperty方法
console.log(p1.hasOwnProperty('Name')); //true
// in关键字
console.log('Name' in p1); //true
作用域链
- 变量的分类:全局变量、局部变量
a.全局变量:定义在全局作用域下面的变量被称为全局变量,全局变量的作用域是整个文档
b.局部变量:定义在函数内部的变量被称为局部变量,局部变量的作用域是定义它的那个函数
c.注意:当全局变量和局部变量同名时,局部变量会将全局变量屏蔽掉,如果要使用全局变量,需要将window.或this.- 作用域链:
a. 所谓作用域链是指,在每个函数内部都有一个属性,这个属性是[[Scope]]属性
,这个属性是不可以操作的。 该属性指向了一个集合,这个集合中保存了当前作用域下面变量对象的地址,以及上级作用域下面的变量对象的地址。这个集合就是作用域链。
b. 所谓变量对象就是指,在每个作用域下面都会有的一个对象,该作用域下面定义的所有的变量和方法都是该这个对象添加的属性和方法,全局作用域下面的变量对象就是window对象
c. 当在使用某个变量时,从先从当前作用域下面变量对象身上查找,如果有则返回其值,如果没有,则沿着作用域链向上级作用域中的变量对象身上查找,如果有则返回其值,如果没有则继续向上查找,以此类推,当找到window对象依然没有找到该变量,那么则报错
闭包
- 定义
a. 从广义讲:被定义在其它函数内部的函数就是一个闭包
b. 从狭义将:外部函数返回的持有外部函数变量的内部函数,被称为闭包- 闭包的作用:可以将外部函数中定义的变量拿到函数外部来操作,即闭包在它所在的外部函数和全局环境间建立起了桥梁
- 闭包的工作原理:
a. 按道理说,每个函数在执行完毕后会从内存中将该函数弹出,如果函数被从内存中弹出,那么该函数的作用域链由于没有东西对它进行引用,那么这个作用域链就会被销毁,作用域链被销毁,那么该函数的变量对象也就没有被引用,变量对象也会被销毁。
b. 闭包之所以可以在外部函数执行完毕后依然能够使用外部环境中的变量,是因为,当外部函数被销毁时,由于闭包中使用了外部函数变量对象中的内容,所以外部函数的变量依然会被保存在内存中。- 闭包的不足:由于闭包会将上级作用域下面的变量对象保存在内存中,那么如果程序中有大量的闭包,势必造成内存的资源浪费。
建议,在不使用闭包的时候,手动将闭包清除
this的使用场景
- 在文档中直接使用this,this代表window对象
- 如果在全局变量或全局函数前面使用this,this代表window对象
- 如果是HTML事件处理程序,那么将this作为事件处理函数的实参,传递给事件处理函数,this代表应用事件的元素
- 如果是DOM0级事件处理程序,事件处理函数中的this代表应用事件的元素
- 如果是DOM2级事件处理程序,事件处理函数中的this代表应用事件的元素
- 在字面量形式创建的对象中,如果将this方式方法内,这个this代表的是当前的字面量对象
- 在构造方法中,如果将this放在属性名称前面,这个this代表的是该构造方法创
- 如果将this放在原型中,它代表的是使用该原型内容的对象
- 在借用构造方法继承时,call中的this代表的是下级构造方法创建的对象
- 如果在闭包中使用this,this代表window
- 间隔调用和延迟调用:间隔调用和延迟调用中的this指向window
- 自执行函数中this指向window