一、类与对象
概念
- 对象是一组无序的相关属性和方法的集合,所有的事物都是对象
- 对象是由属性和方法组成的
- 类抽象了对象的公共部分,它泛指某一大类
- 对象特指某一个,通过类实例化一个具体的对象
基本语法
- 创建类
- new 实例化对象
- 类构造函数 constructor
- 类中添加方法
class Star {
constructor(uname, age) {
this.uname = uname;
this.age = age;
}
sing(song){
console.log(this.name + '唱' + song);
}
}
var ldh = new Star('刘德华', 18);
console.log(ldh.uname);
ldh.sing('冰雨')
类的继承
- 子类可以继承父类中的一些属性和方法
super
关键字:- 可以调用父类的构造函数,也可以调用父类的普通函数
- 子类在构造函数中使用
super
,必须放到this
前面
class Father {
constructor(x, y) {
this.x = x;
this.y = y;
}
say() {
return "我是爸爸";
}
sum() {
console.log(this.x + this.y);
}
}
class Son extends Father {
constructor(x, y) {
super(x, y);
this.x = x;
this.y = y;
}
say() {
console.log(super.say() + "的儿子");
}
subtract() {
console.log(this.x - this.y);
}
}
var son = new Son(5, 2);
son.sum();
son.subtract();
son.say();
类的注意事项
- 在
ES6
中类没有变量提升,所以必须先定义类,才能通过类实例化对象 - 类里面的共有属性和方法一定要加
this
constructor
中的this
指向创建的实例对象,方法里的this
指向这个方法的调用者
二、构造函数和原型
概述
- 在ES6之前,对象不是基于类创建的,由构造函数来定义
new执行过程:
- 在内存中创建一个新的空对象。
- 让this指向这个新的对象。
- 执行构造函数里面的代码,给这个新对象添加属性和方法
- 返回这个新对象(所以构造函数里面不需要return)
构造函数与成员
- 构造函数中的属性和方法我们称为成员,成员可以添加
- 静态成员:在构造函数本身上添加的成员称为静态成员,只能由构造函数本身来访问
- 实例成员:在构造函数内部通过
this
添加的成员称为实例成员,只能由实例化的对象来访问
function Star(uname,age){
this.uname = uname;
this.age = age;
this.sing = function(){
console.log('sing');
}
}
var ldh = new Star('刘德华',18);
// 实例成员 uname
console.log(ldh.uname);
// 静态成员 sex
Star.sex = '男';
console.log(Star.sex);
构造函数原型prototype
- 每一个构造函数都有一个
prototype
属性 - 公共方法定义在
prototype
对象上,共享方法,节约空间 - 原型是一个对象 ,我们也称
prototype
为原型对象 - 原型对象函数里面的
this
指向实例对象
对象原型__proto__
- 对象都会有一个属性
__proto__
指向构造函数的prototype
原型对象 __proto__
对象原型和原型对象prototype
是等价的
constructor
构造函数
- 对象原型
__proto__
和构造函数prototype
原型对象里面都有一个属性constructor
constructor
可以让原型对象重新指向原来的构造函数
function Star(uname,age){
this.uname = uname;
this.age = age;
}
/*
Star.prototype.sing = function(){
console.log('我会唱歌');
}
*/
Star.prototype = {
constructor:Star, //利用constructor 属性指回原来的构造函数
sing:function(){
console.log('我会唱歌');
},
movie:function(){
console.log('我会演电影');
}
}
var ldh = new Star('刘德华',18);
ldh.sing();
console.log(ldh.__proto__ === Star.prototype);
构造函数、实例、原型对象三者之间的关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kWoqKvrp-1661244123946)(E6C1BDD2C3844E5698CE314B4396032B)]
原型链
- 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性
- 如果没有就查找它的原型(也就是
__proto__
指向的prototype
原型对象) - 如果还没有就查找原型对象的原型(
Object
的原型对象) - 依此类推一直找到
Object
为止(null
)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b7vKmov6-1661244123951)(CD98CA726C444EB5AC6A28BEE3C76845)]
扩展内置对象
- 可通过原型对象,对原来的内置对象进行扩展自定义的方法
- 比如给数组增加自定义求偶数和的功能
Array.prototype.sum = function () { ... }
组合继承
- ES6之前并没有给我们提供
extends
继承,我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承 call()
方法- 调用函数:
fn.call()
- 改变函数内
this
指向:fn.call(o,1,2)
// 让fn
中this
指向o
- 调用函数:
function Father(uname,age){
this.uname = uname;
this.age = age;
}
Father.prototype.money = function(){
console.log(10000);
}
function Son(uname,age,score){
// 继承父亲的属性
Father.call(this,uname,age);
// 自己的属性
this.score = score;
}
// 继承父亲的方法
// 不能直接 Son.prototype = Father.prototype
Son.prototype = new Father();
Son.prototype.constructor = Son;
// 自己的方法
Son.prototype.exam = function(){
console.log('孩子要考试');
}
三、ES5中新增的方法
数组方法
forEach()
var arr = [1,2,3];
arr.forEach(function(value,index,array){
console.log('每个数组元素' + value);
console.log('每个数组元素的索引号' + index);
console.log('数组本身' + array);
// forEach中即使有return也不会终止迭代
})
filter()
var arr = [12,66,4,88];
// 返回一个新数组,主要用于筛选数组
var newarr = arr.filter(function(value,index){
return value >= 20;
});
some()
var arr1 = ['red','pink','blue'];
// 返回一个布尔值,是否找到
// 如果找到第一个满足条件的元素则终止循环不在继续查找
var flag1 = arr1.some(function(value){
return value == 'pink';
});
every()
arr.every(item => item.state)
// 判断是否全选
reduce()
arr.reduce((total, item) => (total += item.price * item.count), 0)
// 累加器
字符串方法
trim()
str.trim()
// 去除字符串两端的空格
// trim()方法并不影响原字符串本身,它返回的是一个新的字符串
对象方法
Object.keys(obj)
,返回一个由属性名组成的数组Object.defineProperty(obj, prop, descriptor)
,定义新属性或者修改原有的属性
var obj = {
id:1,
pname:'小米',
price:1999
};
Object.defineProperty(obj,'adress',{
value:'中国山东', // 设置属性的值
writable:false, // 是否可以重写
enumerable:false, // 是否允许遍历(枚举)
configurable:false // 是否允许删除
});
四、函数进阶
函数的定义和调用
//1.自定义函数(命名函数)
function fn(){};
fn(); // fn.call()
function Star(){};
new Star();
//2.函数表达式(匿名函数)
var fun = function(){};
//3.利用new Function('参数1','参数2','函数体')
var f = new Function('a','b','console.log(a+b)');
//4.所有函数都是 Function 的实例(对象)
//5.函数也属于对象
函数内的this指向
- 普通函数:this指向window
- 对象的方法:this指向的是该方法所属对象
- 构造函数:this指向实例对象,原型对象里面的this指向的也是实例对象
- 绑定事件函数:this指向的是函数的调用者
- 定时器函数:this指向window
- 立即执行函数:this指向window
改变函数内的this指向
call()
方法apply()
方法
// 第一个参数是this指向,第二个参数必须是数组(伪数组)
var arr = [1,66,3,99,4];
var max = Math.max.apply(null,arr)
bind()
方法- 不会调用函数,但是能改变函数内部的this指向
- 返回的是原函数改变this之后产生的新函数
- 常用于改变定时器内部的this指向
严格模式
- ES5的严格模式是采用具有限制性JavaScript变体的一种方式,即在严格的条件下运行JS代码
- 开启严格模式
'use strict'; //或 "use strict";
// 可以为脚本开启严格模式,也可以单独为函数开启严格模式
- 变量规定
- 严格模式变量都必须先用var命令声明,然后再使用
- 不能随意删除已经声明的变量
- this指向
- 严格模式下全局作用域中函数中的this是undefined
- 严格模式下,如果构造函数不加new调用,this会报错
- 定时器this还是指向window
- 函数
- 函数不能有重名的参数
- 不允许在非函数的代码块如
if()
,for()
内声明函数
高阶函数
- 高阶函数是对其他函数进行操作的函数
- 高阶函数接收函数作为参数或将函数作为返回值输出
闭包
- 闭包(closure)指有权访问另一个函数作用域中变量的函数
- 闭包的作用:延伸变量的作用范围
for(var i = 0; i < lis.length; i++){
//立即执行函数也称为小闭包,因为立即执行函数里面的任何一个函数都可以使用它的i这个变量
(function(i){
lis[i].onclick = function(){
console.log(i);
}
})(i);
}
递归
- 如果一个函数在内部可以调用其本身,那么这个函数就是递归函数
- 由于递归很容易发生“栈溢出”错误
stack overflow
,所以必须要加退出条件return
浅拷贝与深拷贝
- 浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用(地址)
- 因为浅拷贝拷贝的是地址,当地址内数据发生变化时,那么指向地址的对象读取的数据也发生了变化
- es6新增方法可以浅拷贝
Object.assign(target, source)
- 深拷贝拷贝多层,每一级别的数据都会拷贝
- 深拷贝:把旧内存空间里面的数据重新复制一份(开辟了一块新的内存空间),给了新的对象,所以当新的对象里面的值发生改变时,旧的对象不会发生改变
五、正则表达式
概述
- 正则表达式是用于匹配字符串中字符组合的模式
- 在JavaScript中,正则表达式也是对象
- 用途:匹配,替换,提取
创建正则表达式
// 通过调用 RegExp 对象的构造函数创建
var regexp = new RegExp(/表达式/);
// 通过字面量创建
var 变量名 = /表达式/
测试正则表达式
regexObj.test(str)
// regexObj是写的正则表达式
// str我们要测试的文本
// 检测str文本是否符合我们写的正则表达式规范,返回true或false
正则表达式中的特殊字符
- 边界符
^
$
- 字符类
[ ]
,表示有一系列字符可供选择,只要匹配其中一个就可以了 - 范围符
-
- 取反
[^ ]
- 量词符
*
+
?
{n}
{n,}
{n,m}
/abc/
// 字符串中含有'abc'
/^abc/
// 字符串以'abc'开头
/abc$/
// 字符串以'abc'结尾
/^abc$/
// 精确匹配字符串'abc'
/[abc]/
// 只要包含'a'或'b'或'c'
/^[^a-zA-Z0-9_-]$/
// 不包含大小写字母或数字或'_'或'-'中任意一个
/^a*$/
// a重复出现>=0次
/^a+$/
// a重复出现>=1次
/^a?$/
// a重复出现0或1次
/^a{3}$/
// a重复出现3次
/^a{3,}$/
// a重复出现>=3次
/^a{3,16}$/
// a重复出现>=3且<=16次
var reg = /^[a-zA-Z0-9_-]{6,16}$/;
// 这个模式用户只能输入6-16位含英文字母 数字 下划线 短横线
- 预定义类:指的是某些常见模式的简写方式
\d
:匹配0-9之间任意一个数字,相当于[0-9]
\D
:匹配除0-9之外任意字符,相当于[^0-9]
\w
:匹配任意字母,数字和下划线,相当于[A-Za-z0-9_]
\W
:匹配任意除字母,数字和下划线之外任意字符,相当于[^A-Za-z0-9_]
\s
:匹配空格(换行符,制表符,空格符等),相当于[\t\r\n\v\f]
\S
:匹配除空格之外任意字符,相当于[^\t\r\n\v\f]