1 面向对象操作
- 回顾对象的基本概念
- 面向对象的相关概念
- 面向对象的特征和操作的实现方式
- 小练习
2 函数的相关内容
- 函数的属性和方法
- 函数的其他使用方式
- 自调用函数
- 回调函数
- 闭包函数
- 递归函数
3 正则表达式
- 介绍:是一个用来操作字符串的工具(内置对象)
- 对象的创建方式
- 单个对象创建方式:{} new Object()
- 多个对象创建方式:
- 内置对象
- Array
- Date
- String
- 自定义构造函数
- 使用方式
- 命名规则:首字母大写
- 调用规则:调用前必须设置new
- 内部操作:通过this给对象设置属性或方法
- new的作用:
- 创建了一个对象
- 将对象返回
- 将this修改为这个对象
- 调用构造函数
- 推荐无论如何都要添加()
- this的使用:
- 全局作用域中:window对象,没用
- 普通调用的函数中
- 默认this为window,也没用
- 作为方法调用的函数中(使用最多的情况) (重要!!!)
- 默认this为当前对象(函数调用者)
- 构造函数中的this (固定用法)
- 被new设置为对象,我们无法操作
- 对象的基本操作
- 分类:
JavaScript的数据类型分为2类
- 简单类型(基本类型)
- string 字符串
- number 数值
- boolean 布尔
- null 空
- undefined 未定义
- 复杂类型
- Object
- Array
- Date
- Math
- String
- 自定义类型(自定义构造函数)
Js中只有对象一种复杂类型,因为内置功能很多,
根据具体的功能分类,有划分为了多种类型
- 对象的使用分类:
- 数据存储功能
- 数组: []
有序的数据存储方式
- 对象: {}
无序的数据存储方式
- 适用于数据需要进行单独标识的场景
- 作为工具使用
- 见前面的复杂类型部分
- 对象的属性操作
- 概念:对象是由属性组成的,属性由属性名和属性值组成
- 方法:方法也是属性,只是保存了函数值,为了区分,起了个新名字而已。
- 操作方式
- 对象.属性名
- 对象['属性名']
- 属性名为字符串值,或通过变量保存时,必须使用这种方式
- 遍历
- 遍历方式: for..in
- 删除方式:
delete 对象.属性名; 删除了属性
// w3c标准和ECMA标准的关系?
// - ECMA标准:js基础语法标准
// - w3c标准:html、css、webAPI
*/
// 面向对象的概念:
// - 面向过程
// - 指的是在编程中,专注于实现功能的'过程',专注于实现的具体的细节。
// - 例如:冒泡排序,需要考虑有几个循环,每个循环多少次,怎么比较和交换。。
// - 面向对象(拿来主义)
// - 指的是在编程中,考虑效果中需要使用哪几部分功能,找到可以帮助我们实现功能的工具(对象)进行操作即可。
// - 例如:操作中需要对某个数组排序,找到数组的sort方法,直接排序后进行后续操作即可。
// 能不能说面向对象操作比面向过程好呢?
// - 不是一个层面的考虑方式,无法直接比较。
// - 例如:我们使用sort是一种面向对象的操作形式,但是sort功能在实现时也是通过面向过程来操作的。
// - 我们可以将两个部分的关系理解为:面向对象是基于面向过程的。
/*
var arr = [5, 2, 3, 1];
arr.sort();
console.log(arr); */
// 吃饭: 自己做饭(面向过程)、 去饭馆吃饭(面向对象)
// 回忆以前我们做过的操作属于哪种使用方式:
// - 面向过程:以前的大部分代码都是面向过程的
// - 面向对象:内置对象操作,jQuery
// 面向对象操作的3个特征:
// - 封装:指的是对象的封装
// - 以前的封装是函数封装,现在的封装是对象的封装,
// 其实就是基于函数封装操作,将功能分类后保存到对象中进行使用。
// - 继承:
// - 为了实现更好的功能复用(jack和jack爸爸的例子)
// - 多态:
// - 一个功能被不同对象操作时,操作效果不同
// 将math相关的功能保存到obj中,就实现了基本函数封装的对象封装操作
/* var obj = {
mathFun1 : function () {
// 求和功能
},
mathFun2 : function () {
// 计算差功能
},
mathFun3 : function () {
// 计算乘法功能
}
}; */
/* function CreateObj (name, age) {
this.name = name;
this.age = age;
this.sayHi = function () {
console.log('你好,我的名字是' + this.name);
};
} */
// 通过new的方式可以创建具有构造函数中功能的对象
// 我们将这种对象称为'实例对象'
/* var c1 = new CreateObj('jack', 18);
var c2 = new CreateObj('rose', 21); */
// 通过观察我们发现c1和c2两个实例对象的属性值不同,很正常
// c1和c2的sayHi方法值相同不?
// console.log(c1, c2);
/* console.log(c1.sayHi);
console.log(c2.sayHi); */
// 通过观察我们发现c1和c2的sayHi方法值长得一样,但推测不是同一个函数
// - 可以通过==或===进行比较
// - 注:对复杂类型进行==或===比较时,必须是同一个值才能返回true
/* console.log(c1.sayHi == c2.sayHi); // false,说明不是同一个函数
console.log(c1.sayHi === c2.sayHi); // false,说明不是同一个函数 */
// 出现的问题:函数的作用是重用,操作时不应当设置多个相同功能的函数
// 解决方式:将方法值设置为命名函数统一保存,让功能可以重用
vartemp= {
sayHi:function() {
console.log('你好,我的名字是'+this.name);
},
sayHehe:function() {
console.log('你好,我的名字是'+this.name);
}
};
functionCreateObj(name,age) {
this.name=name;
this.age=age;
// 将sayHi函数体设置给this.sayHi
this.sayHi=temp.sayHi;
this.sayHehe=temp.sayHehe;
}
varc1=newCreateObj('jack',18);
varc2=newCreateObj('rose',21);
// 检测后:c1和c2的sayHi是用一个函数,达到了改进的目的
console.log(c1.sayHi===c2.sayHi);// true
// 新的问题:
// - 为了优化构造函数,设置了命名函数保存,这些函数被自动设置为window的方法
// - window的方法变多了,导致执行速度变慢..
// - 任意的一个对象,属性越多,访问的速度越慢
// 解决方式:
// - 设置一个临时的对象,用来统一保存构造函数中的方法值
// prototype 原型
// - 任意函数都自带prototype属性
// prototype的值,默认就是一个对象,就是用来保存构造函数中的方法使用的。
functionCreateObj(name) {
this.name=name;
this.age=18;
this.hobbies= ['吃','喝'];
// 之前的方法设置方式:
/*
this.sayHi = function () {
console.log('你好,我的名字是' + this.name);
};
this.sayHehe = function () {
console.log('呵呵呵');
};
*/
}
// console.log(CreateObj.prototype);
// 以后的方法设置方式:
// - 考虑某个函数中的this时,一定先考虑函数是如何执行的
CreateObj.prototype.sayHi=function() {
console.log('你好,我的名字是'+this.name);
};
CreateObj.prototype.sayHehe=function() {
console.log('呵呵呵');
};
varc1=newCreateObj('jack',18);
varc2=newCreateObj('rose',21);
c1.sayHi();// c1在调用sayHi方法,sayHi中的this就是c1
c2.sayHi();// c2在调用sayHi方法,sayHi中的this就是c2
// console.log(c1.sayHi === c2.sayHi); // true
// 小结论:
// 将方法设置给prototype后,实例对象可以直接使用,也是统一保存的方法值
// - 以后设置方法时,统一设置给 构造函数.prototype 即可
// 对象属性的基本查找方式:
// - 1 查找对象自身,如果存在,就使用
// - 2 如果没有对应功能,在查找__proto__,也就是构造函数的原型
// - 如果原型中存在对应功能,也可以使用
// 从语法角度观察,Array是构造函数,arr就是实例对象
vararr=newArray(1,2,3,4,5);// 相当于[1, 2, 3, 4, 5]
arr.push(8);
console.log(arr);
// 通过观察arr,我们发现内置对象设置方法时,采用的方式与我们相同,都是设置在了prototype中
// 如果我们希望给内置构造函数Array增加方法,设置在Array.prototype中即可
// 例如:设置一个用于数组求和的方法
/* function getSum (arr) {
var sum = 0;
for (var i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
console.log(getSum(arr)); */
// 将getSum设置为数组的方法,任意数组均可使用
Array.prototype.getSum=function() {
varsum=0;
for(vari=0;i<this.length;i++) {
sum+=this[i];
}
returnsum;
};
console.log(arr.getSum() );
// 我们自己书写的代码可以在控制台输出查看
// 例如: console.log(arr.getSum);
// 内置的功能无法查看代码,查看结果为 ƒ push() { [native code] }
// 例如: console.log(arr.push);
// 实际使用方式:
// - 这个属性是给示例对象访问的,用来确定实例对象是通过哪个构造函数创建的。
// - 功能作用:类型检测操作
// typeof 只能检测除null的简单类型和function
// instanceof
// - 以后希望确定当前对象的类型时,检测constructor即可,比instanceof好用一些
// - constructor的作用非常单纯,就是用来检测类型,确定了类型就确定了功能
// 作用域链回顾:
// - 作用:用来描述变量名/函数名的查找方式
// - 沿作用域链查找
// - 查找的最终位置:全局作用域
// 原型链:
// - 原型链是由一个或多个原型组成的结构。
// - 作用:用来描述对象属性的查找方式
// - 查找方式:沿原型链查找
// - 查找的最终位置:Object.prototype