1. 正则表达式:
2. String中的正则API:
1. 正则表达式:
2. String中的正则API:
查找:
1. 查找一个固定的关键词出现的位置:
var i=str.indexOf("关键词"[,starti])
在str中从starti位置开始找下一个"关键词"的位置
如果省略starti,则默认从0位置开始向后找
返回: “关键词”第一字所处位置的下标
如果找不到,返回-1
问题: 只支持查找一个固定不变的关键词
2. 用正则表达式查找一个关键词的位置:
var i=str.search(/正则/i);
在str中查找符合"正则"要求的敏感词
返回值: 关键词的位置
如果找不到,返回-1
问题: 正则默认区分大小的!
解决: 在第2个/后加后缀i,表示ignore,意为:忽略大小写
问题: 只能获得关键词的位置,不能获得关键词的内容
解决: match
3. match:
1. 查找一个关键词的内容和位置:
var arr=str.match(/正则/i);
在str中查找符合"正则"要求的敏感词的内容和位置
返回值: 数组arr:[ "0":"关键词", "index": 下标i ]
如果找不到: 返回null
问题: 只能查找第一个关键词,不能查找更多关键词
2. 查找所有关键词的内容:
var arr=str.match(/正则/ig) //g global 全局/全部
返回值: 保存多个关键词内容的数组
问题: 只能找到内容,无法获得位置
4. 即获得每个关键词的内容,又获得每个关键词的位置
reg.exec()
替换: 将找到的关键词替换为指定的新值
2种:
1. 简单替换: 将所有关键词替换为统一的新值
str=str.replace(/正则/ig,"新值")
查找str中所有符合“正则”要求的关键词,都替换为统一的新值。
问题: 所有字符串API都无权修改原字符串,只能返回新字符串。
解决: 如果希望替换原字符串,就必须自己手动赋值回原变量中
2. 高级替换: 根据每次找到的关键词不同,动态选择要替换的新值
str=str.replace(/正则/ig, function(kword){
根据kword的不同,动态生成新值
return 新值
})
查找str中所有符合“正则”要求的关键词
每找到一个关键词,就自动调用一次回调函数
每次调用回调函数时自动传入本次找到的关键词给kword
回调函数中根据每次收到kword的不同,动态返回新值给replace函数
replace函数自动将回调函数返回的新值,替换到字符串原关键词位置。
1. String的正则API
替换:
衍生操作: 删除关键字: 其实将关键词替换为""
切割: 将一个字符串,按指定的切割符,切割成多段子字符串
2种:
1. 简单切割: 切割符是固定的
var arr=str.split("切割符")
将str按指定的"切割符",切割为多段子字符串,保存在数组arr中
固定套路: 打散字符串为字符数组
var chars=str.split("")
2. 复杂切割: 切割符不是固定的
var arr=str.split(/正则/i)
2. RegExp对象:
什么是: 保存一条正则表达式,并提供了用正则表达式执行验证和查找的API 的对象
何时: 只要在程序中保存和使用正则表达式,都要用RegExp对象
如何:
创建:
1. 用/创建(直接量): var reg=/正则/ig
何时: 如果正则表达式是固定不变的
2. 用new创建: var reg=new RegExp("正则","ig")
何时: 如果正则表达式需要在运行时才动态生成时
API:
1. 验证:
var bool=reg.test(str)
用正则reg,检测str是否符合正则的格式要求
问题: 正则默认只要找到部分内容与正则匹配就返回true
解决: 必须从头到尾完整匹配,才返回true
只要验证,必须前加^后加$,表示从头到尾的意思
2. 查找:
获取每个关键词的内容和位置:
var arr=reg.exec(str)
在str中查找下一个符合reg要求的关键词的内容和位置
如果反复调用reg.exec(),则自动会向后找下一个。
返回值: arr:[ "0":"关键词", "index": 关键词位置 ]
3. Function
什么是函数: 封装一项任务的步骤清单代码段的对象,再起一个名字。
为什么: 重用!
何时: 只要一段代码可能被反复使用,都要创建函数。
如何:
创建: 见PPT function1
重载(overload):
什么是: 相同函数名,不同形参列表的多个函数,在调用时,可自动根据传入实参的不同,选择对应的函数调用
为什么: 减少函数名的数量,减轻维护的负担
何时: 一件事,可能根据传入的参数不同,执行不同的操作时
如何:
问题: js语法默认不支持重载
因为js不允许多个同名函数同时存在
如果存在,最后一个函数会覆盖之前所有
解决: 使用arguments对象变通实现
什么是arguments对象: 每个函数内自动创建的,准备接受所有传入函数的实参的 类数组对象
自动创建: 不用自己创建,就可直接使用
接受所有实参:
类数组对象: 长的像数组的对象
vs 数组: 相同: 1. 下标 2. length 3. 遍历
不同: 类型不同,API不通用
何时: 只要不确定将来传入函数的参数个数时,就不定义形参列表,而是用arguments接住所有的实参值。
匿名函数:
什么是: 定义函数时,不写名的函数
何时: 如果一个函数只用一次,不会反复使用,就不起函数名
为什么: 节约内存!——使用一次后,自动释放!
如何:
2种场景:
1. 回调函数: 自己定义的函数,自己不调用,而是传给其它对象或函数,被别人调用。
arr.sort(function(a,b){return a-b})
xhr.onreadystatechange=function(){ ... }
pool.query(sql,[参数],function(err,result){ ... })
2. 匿名函数自调: 定义函数后,立刻自己调用自己
为什么: 避免使用全局变量,造成全局污染
何时: 所有js代码都应该封装在一个匿名函数自调中
如何:
(function(){
...
})()//调用后,匿名函数内的局部变量都释放了
1. Function
2. OOP
1. Function
作用域和作用域链
闭包
2. OOP
什么是对象: 程序中,描述现实中一个具体事物的程序结构
为什么: 便于维护
什么是面向对象: 程序中,都是先将多个事物的属性和功能,封装为多个对象,再按需调用对象的成员
何时: 今后,几乎所有程序,都用面向对象方式实现的
如何: 封装,继承,多态——三大特点
封装:创建一个对象,集中保存一个具体事物的属性和功能
为什么: 便于大量数据维护
何时: 只要使用面向对象编程,都要先封装对象,再按需使用对象的成员
如何: 3种:
1. 用{}:
var obj={
属性名: 值,
... : ... ,
方法: function(){ ... this.属性名... },
... : ...
}
访问对象的成员: =属性+方法
属性其实就是保存在对象中的变量
对象.属性
方法其实就是保存在对象中的函数
对象.方法()
this: 见this.wmv
什么是: 在函数调用时,自动指向.前的对象的关键词
为什么: 避免在对象的方法中写死对象名,形成紧耦合。
何时: 只要对象自己的方法,想访问自己的成员时,都要加this.
强调: 鄙视时:
1. this和定义在哪儿无关,只和调用时.前的对象有关
2. 全局函数调用,没有., this默认指window
2. 用new创建: 2步:
var obj=new Object();
obj.属性名=值;
... = ...;
obj.方法名=function(){ ... this.属性名 ...}
揭示: js中一切对象底层,都是关联数组
1. 访问不存在的成员,不报错,返回undefined
2. 强行给不存在的成员赋值,不报错,而是强行赋值新成员
3. 同样可用for in循环遍历一个对象中的所有成员
4. 访问下标: 2种:
1. obj["下标"] 如果属性名需要动态获得
2. obj.下标 如果属性名是写死的
问题: 一次只能创建一个对象,如果反复创建多个相同结构的对象时,代码会很冗余
解决: 用构造函数创建对象:
3. 用构造函数反复创建多个相同结构的对象:
什么是构造函数: 描述同一类型所有对象的统一结构的函数
何时: 反复创建多个相同结构的对象
如何:
定义构造函数:
function 类型名(形参1,形参2,...){
this.属性名=形参1;
this. ... =形参2;
this.方法名=function(){ ... this.属性名 ...}
}
反复调用构造函数,创建多个相同类型的对象
var lilei=new 类型名(实参,...);
new 4件事:
1. 创建一个新的空对象: {}
2. ?
3. 用新对象调用构造函数:
自动将构造函数中的this->new
通过强行赋值新属性的方式,自动添加规定的属性到新对象中,并将参数值,保存到新对象的对应属性中
4. 返回新对象的地址给变量
构造函数优点: 重用结构
缺点: 无法节约内存!
继承:
什么是: 父对象的成员,子对象无需重复创建就可直接使用
为什么: 重用代码,节约内存
何时: 只要在多个子对象中包含部分相同的成员时
如何:
/****** 不用你做 *******/
js中的继承都是继承原型对象(prototype)
什么是原型对象: 集中保存所有子对象共有成员的父对象
创建原型对象: 买一赠一
每创建一个构造函数,就附赠一个空的原型对象
构造函数.prototype
何时继承:
new的第2步: 让新对象自动继承构造函数的原型对象: 新对象._ _proto_ _=构造函数.prototype
封装:3种
继承:
自有属性和共有属性:
自有属性: 保存在当前对象本地,仅归当前对象自有的属性
共有属性: 保存在原型对象中,归多个子对象共有的属性
取值/访问时: 对象.成员名
修改时: 修改自有属性: 子对象.属性=值
修改共有属性: 原型对象.共有属性=值
如果强行用子对象.共有属性=值
后果: 为子对象自己添加一个同名的自有属性,从此子对象与父对象再无关系。——错误!
内置对象的原型对象:
内置对象: ES标准中规定的,浏览器已经实现了的,咱们可以直接使用的对象
js内置对象: 11个:
String Number Boolean
Array Date RegExp Math
Error
Function Object
global
其实,每种内置对象(除Math和global外)都是一种类型:
都由两部分组成:
1. 构造函数: 创建该类型的子对象
2. 原型对象: 保存该类型共有的函数
原型链:
什么是: 多级原型对象逐级引用形成的链式结构
作用: 1. 保存了一个对象可用的所有成员
2. 控制着成员的使用顺序: 先自有,再共有
多态:
什么是: 一个函数在不同情况下表现出不同的状态
2种:
1. 重载:
2. 重写(override): 子对象中定义了和父对象中同名的成员
何时: 只要子对象觉得父对象的成员不好用,就要定义自有的,来屏蔽父对象的。
自定义继承: 见1_自定义继承.pptx
2. ES5:
1. 严格模式:
什么是: 比普通js运行要求更严格的模式
为什么: js语言本身有很多广受诟病的缺陷
何时: 今后所有js代码都要运行在严格模式下
如何: 在当前作用域的顶部: "use strict";
要求:
1. 禁止给未声明的变量赋值:
2. 静默失败升级为错误:
静默失败: 执行不成功,也不报错!
3. 禁用了arguments.callee
arguments.callee: 在调用函数时,自动获得当前正在执行的函数本身。
何时: 专门用于在递归算法中,代替写死的函数名
递归的问题: 效率极低!——重复计算量太大!
解决: 几乎所有的递归都可以用循环代替
4. 普通函数调用和匿名函数自调中的this不再指向window,而是undefinde
1. OOP
静态(static)方法:
什么是实例(instance)方法: 必须先有一个实例对象,才能调用的方法
比如: var arr=[1,2,3]; arr.sort()
var str="Hello"; str.toUpperCase()
限制: 只有当前类型的子对象,才能使用的方法
什么是静态方法: 不需要任何实例,就可用类型名直接调用的方法
比如: Object.setPrototypeOf()
何时: 2种:
1. 不确定使用该方法的对象的类型时
2. 调用函数时,暂时无法确定要使用该函数的对象是什么
如何定义:
定义实例方法: 将方法添加到原型对象中
定义静态方法: 将方法添加到构造函数对象上
构造函数.静态方法=function(){ ... }
2. ES5:
保护对象:
为什么: js中的对象毫无自我保护能力
何时: 如果不希望别人擅自修改对象的属性和结构时
如何:
保护属性:
将所有属性划分为2大类:
命名属性: 可用.访问到的属性
又分为2类:
数据属性: 直接存储属性值的属性
访问器属性: 不实际存储属性值,仅负责提供对另一个数据属性的保护。
内部属性: 不能用.访问到的属性
数据属性:
ES5规定,每个数据属性,其实是一个缩微的小对象
每个属性对象其实包含四个特性: {
value: 实际存储属性值,
writable: 控制是否可修改,
enumerable: 控制是否可被for in遍历,但用.依然可以访问
configurable: 控制是否可删除该属性
控制是否可修改其它两个特性
默认: 三个开关都是true
获取一个属性的四大特性:
var attrs=Object.getOwnPropertyDescriptor(obj,"属性名")
获得obj对象的指定"属性"的四大特性
打开和关闭开关:
Object.defineProperty(obj,"属性名",{
重新定义obj的指定"属性"的开关
开关: true/false,
... : ...
})
问题: 一次只能修改一个属性的四大特性
解决:
Object.defineProperties(obj,{
属性:{
开关:true/false,
... : ...
},
属性:{
... ...
}
})
问题: 无法使用自定义规则保护属性
解决:
访问器属性:
何时: 只要使用自定义规则保护一个数据属性时
如何:
前提: 必须先有一个隐藏的数据属性,实际存储属性值
定义访问器属性:
使用访问器属性:
保护结构: 禁止添加/删除对象中的属性
3个级别:
1. 防扩展: 禁止添加新属性
Object.preventExtensions(obj)
禁止给obj对象添加任何新属性
原理: 每个对象中都有一个内部属性: extensible:true
preventExtensions()将对象的extensible:false
2. 密封: 在兼具防扩展同时,再禁止删除现有属性
Object.seal(obj)
禁止向obj中添加新属性
禁止删除obj中现有属性
原理: extensible:false
每个属性的configurable:false
3. 冻结: 在兼具密封的基础上,同时禁止修改所有属性值
Object.freeze(obj)
禁止向obj中添加新属性
禁止删除obj中现有属性
禁止修改任何属性的值
原理: 自动将每个属性的writable改为false
Object.create()
什么是: 创建一个新对象,让新对象继承指定的父对象
何时: 在没有构造函数的情况下,也想创建子对象继承父对象时
如何:
var child=Object.create(father,{
自有属性:{
value:值,
三个开关...
}
})
1. ES5
2. ES6
1. ES5
替换this:
1. 临时调用一次函数,并临时替换一次this:
call: 传入函数的每个实参必须作为一个单独的参数传入
apply: 传入函数的每个实参必须放在一个数组中整体传入
何时: 如果所有实参是放在一个数组中给你的
2. 不调用函数,而是创建一个原函数的副本,但永久绑定this和部分参数值: bind
何时: 修改回调函数的this时只能用bind
数组API:
1. 查找: indexOf: 同String中的indexOf
何时: 在数组中查找一个指定元素的位置时
2. 判断:
判断数组中的元素是否符合要求
1. 判断数组中的元素是否都符合要求
var bool=arr.every(function(elem, i, arr){
return 判断结果
})
every会自动拿着回调函数在每个元素上执行一次:
参数: elem自动得到当前元素值
i 自动得到当前位置
arr 自动得到当前数组对象
返回值: 利用获得的参数,判断当前元素是否符合要求,并返回判断结果。
只有回调函数在每个元素上执行都返回true时,才整体返回true。只要碰到一个false,就返回false
2. 判断数组中是否包含符合要求的元素
var bool=arr.some(function(elem, i, arr){
return 判断条件
})
3. 遍历API: 对数组中每个元素执行相同的操作
1. 遍历原数组中每个元素,执行相同的操作:
arr.forEach(function(elem, i, arr){
对原数组中的元素值,执行操作
})
2. 依次取出原数组中每个元素,执行相同的操作后,放入新数组中返回:
var newArr=arr.map(function(elem,i,arr){
return 新值
})
4. 过滤和汇总:
过滤: 复制出数组中符合条件的元素,组成新数组返回
var subArr=arr.filter(function(elem,i,arr){
return 判断条件
})
汇总: 对数组中每个元素的值进行统计,得出一个汇总的结果。
var result=arr.reduce(
function(prev,elem,i,arr){
//prev: 获得截止目前的临时汇总值
return prev+elem
},
base//起始时的基数
)
2. ES6: 不改变原理的基础上,让API变的更简化
let: 代替var用于声明变量
var的缺点:
1. 声明提前:
2. 没有块级作用域:
let的优点:
1. 阻止了声明提前
2. 让let所在的块({...})也变为一级作用域
参数增强:
1. 默认值: ES6中可以给形参提前设置一个默认值,调用时,如果没有给实参,就自动启用默认值代替。
如何: function fun(形参1, 形参2,..., 形参n=默认值){}
强调: 带默认值的形参必须出现在参数列表的末尾
2. 剩余参数:
代替arguments:
arguments的问题:
1. 不是纯正的数组类型,而是类数组对象,导致数组的所有API,arguments不能使用
2. 只能接住所有参数,不能有选择的接住部分参数
如何使用剩余参数:
function fun(形参1, 形参2,...数组名){
//数组中就接住了除形参1,形参2以外的剩余的实参
//且"数组"是纯正的数组类型,可以使用所有数组家的API
}
剩余参数的优点:
1. 是纯正的数组,可使用所有数组家API
2. 可有选择的获得剩余参数
3. 散播(spread):
代替apply,用于专门打散数组类型参数为单个值
apply的问题: 其实apply的主要功能是替换this,顺便打散数组类型参数
何时: 只要单纯希望打散数组类型参数为单个值时
如何:
调用时: fun(...数组名)
先把数组打散后,再分别传给fun
相当于: fun(数组[0],数组[1],数组[2],...)
1. ES6
箭头函数: 简写一切匿名函数
1. 去function变=>
2. 如果只有一个参数,可省略()
3. 如果函数体只有一句话,可省略{}
如果仅有的一句话是return... ,则必须省略return
特性: 内外this通用!
如果和this无关时,或希望内外this通用时,可改箭头函数
如果不希望内外this通用时,就不能用箭头函数
解构: 提取出一个大的对象中的部分成员,单独使用。
1. 数组解构: 下标对下标:
var arr=[elem1, elem2,...];
|| ||
var [变量1,变量2,...]=arr;
变量1=elem1
变量2=elem2
2. 对象解构: 属性对属性
var obj={属性1:值1, 属性2:值2, ... }
|| ||
var {属性1: 变量1, 属性2:变量2, ... }=obj
变量1=值1;
变量2=值2;
3. 参数解构: 其实是对象解构在函数传参时的应用
何时: 多个形参都不确定是否有值时
如何: 1. 定义函数时: 将所有形参都定义在对象结构中
function fun({
url:url,
type:type,
data:data,
dataType:dataType
}){
}
可简写为: function fun({url, type, data, dataType}){
2. 调用时: 所有实参都要放在一个对象结构中整体传入
fun({
url:"http://localhost:3000/index",
type:"get",
//data:,
dataType:"json"
})
结果:
形参url ="http://localhost:3000/index
形参type="get"
形参data=undefined
形参dataType="json"
优点:
1. 与参数个数无关
2. 与参数顺序无关
for of: 遍历索引数组
1. for:
for(var i=0;i<arr.length;i++){
arr[i] //当前元素
}
2. forEach:
arr.forEach( (elem,i,arr)=>{ elem //当前元素值 })
不灵活:
1. 不能控制顺序
2. 不能控制步调
3. for of
for(var elem of arr){
elem //当前元素值
}
不灵活: 只能获得元素值,不能获得元素位置
vs for in:
for of: 可遍历数字下标的索引数组或类数组对象
for in: 只能遍历非数字下标的关联数组或对象
class: 对整个面向对象的简化:
1. 对单个对象直接量的简化:
var obj={
属性1: 值1,
属性2 : 变量,
//如果属性名刚好和变量名相同,则只写一个
方法名:function(){//所有方法,不再需要:function
... ...
}
}
2. 对一种类型定义的简化: class
1. 用class{}包裹构造函数和原型对象方法
2. 将构造函数名提升为类型名,构造函数统一更名为constructor
3. 所有原型对象方法不用再添加到Prototype中,而是直接写在class内,与构造函数平级(不要逗号)
class Plane {
constructor (fname,speed,score){
this.fname=fname;
this.speed=speed;
this.score=score;
}
fly(){ ... }
getScore(){ ... }
}
3. 继承:
1. 让子类型继承父类型:
class Child extends Father{
extends代替了Object.setPrototypeOf(...)
2. 子类型构造函数中必须先借用父类型构造函数:
class Child extends Father{
constructor(...){
super(参数,...)//借父类型的构造函数
this.xxx=xxx;
}
}
super代替了Father.call(this,...)
super中不要加this!
4. 访问器属性:
class 类名{
constructor(..., age){
... ...
半隐藏的_age属性
this.age=age;
}
get age(){ return this._age;}
set age(value){验证value并赋值}
}
5. 静态方法:
class 类名{
constructor(){
}
//必须使用当前类型的子对象才能调用的方法,称为实例方法。
实例方法(){ ... }
//不需要使用当前类型的子对象,就可用类型名直接调用的方法
static 静态方法(){ ... }
}
调用时:
//静态方法不需要提前创建任何该类型的子对象,就可用类型名直接调用
类型名.静态方法()
var obj=new 类型名()
//实例方法要求必须先创建该类型的子对象,才可用子对象调用实例方法。
obj.实例方法()
来源:https://www.cnblogs.com/liuqingqing-bloom/p/12389923.html