一、函数进阶
1.函数的定义
- 自定义函数 function fun(){}
- 函数表达式(匿名函数) var fun=function(){}
- 利用new Function('参数1',‘参数2’,‘函数体’)
var f=new Function('a','b','console.log(a+b)')
f(1,2)
2.函数的调用
3.函数内this指向
函数的不同调用方式决定了this的指向不同,一般指向我们的调用者.
- 普通函数:this指向了window
- 对象方法:this指向对象
- 构造函数:this指向了实例对象,原型对象里面的this也是指向实例对象
- 绑定事件函数:this指向的是事件的调用者
- 定时器函数:this指向的是window
- 立即执行函数:this指向的是window
// 函数调用
// 1.普通函数,this指向window
function fn(){
console.log('this指向'+this);
}
fn()
// 2.对象的方法,this指向对象o
var o={
sayhi:function(){
console.log('this指向'+this);
}
}
o.sayhi();
// 3.构造函数,this指向实例对象ldh,原型对象里面的this也是指向实例对象ldh
function Star(){};
var ldh=new Star()
// 4.绑定事件函数,this指向的是事件的调用者btn
btn.onclick=function(){};//点击了按钮就可以调用这个函数
// 5.定时器函数,this指向的是window
setInterval(function(){},1000);//这个函数是定时器函数
// 6.立即执行函数,this指向的是window
(function(){
console.log('人生的巅峰');
})()
//立即执行函数是自动调用
4.改变函数内的this指向
- call()
-
fun.call(thisArg, arg1, arg2, ...)
-
thisArg:在 fun 函数运行时指定的 this 值
-
arg1,arg2:传递的其他参数
-
call可以调用函数,可以改变函数内的this指向
-
call的主要作用可以实现继承
-
- apply()
-
fun.apply(thisArg, [argsArray])
-
thisArg:在fun函数运行时指定的 this 值
-
argsArray:传递的值,必须包含在数组里面
-
也是调用函数,改变函数内的this指向
-
但是它的参数必须是数组(伪数组)
-
apply的主要应用,利用apply借助于数学内置对象来求最大值和最小值
-
var arr=[1,16,3,99,4] Math.max.apply(Math,arr);
-
- bind()
-
fun.bind(thisArg, arg1, arg2, ...)
-
thisArg:在 fun 函数运行时指定的 this 值
-
arg1,arg2:传递的其他参数
-
不会调用函数,但是会改变this指向
-
返回值是原函数改变this之后产生的新函数
-
// 3.bind() var o={ name:'andy' } function fn(){ console.log(this); } var f=fn.bind(o) console.log(f);
-
call apply bind 总结
相同点:
都可以改变函数内部的this指向.
区别点:
主要应用场景:
5.严格模式
严格模式对正常的 JavaScript 语义做了一些更改:
严格模式可以应用到整个脚本或个别函数中。因此在使用时,我们可以将严格模式分为为脚本开启严格模式和为函数开启严格模式两种情况
- 在所有语句前面放一个语句use strict
<!-- 为脚本开启严格模式 -->
<script>
'use strict'
// 下边的js代码执行严格模式
</script>
<script>
(function(){
'use strict'
})()
</script>
<!-- 为某个函数开启严格模式 -->
<script>
// 只为fn函数开启严格模式
function fn(){
'use strict'
// 函数内容的js代码执行严格模式
}
</script>
严格模式中的变化
- 变量规定
- 在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,变量都必须先用var 命令声明,然后再使用。
- 严禁删除已经声明变量。例如,delete x; 语法是错误的
- 严格模式下的this指向
- 以前全局作用域函数中的this在window;严格模式下this指向undefined
- 以前构造函数不使用new也可以当成普通函数调用,this指向全局对象; 严格模式下this指向undefined,如果赋值会报错
- new实例化的构造函数this还是指向创建的实例对象
- 定时器this还是指向window
- 事件、对象中this还是指向调用者
- 函数变化
- 函数不能有重名的参数
- 函数必须声明在顶层
6.高阶函数
高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。
7.闭包
闭包(closure)指有权访问另一个函数作用域中变量的函数
简单理解就是 ,一个作用域可以访问另外一个函数内部的局部变量。
function fn1(){ // fn1 就是闭包函数
var num = 10;
function fn2(){
console.log(num); // 10
}
fn2()
}
fn1();
闭包主要作用:延伸了变量的作用范围
// 利用闭包实现点击li打印当前索引号
var lis=document.querySelector('.nav').querySelectorAll('li');
for(var i=0;i<lis.length;i++){
(function(i){
lis[i].onclick=function(){
console.log(i);
}
})(i);
}
// 利用闭包实现3秒后打印全部的li内容
for(var i=0;i<lis.length;i++){
(function(i){
setTimeout(function(){
console.log(lis[i].innerHTML);
},3000)
})(i)
}
8.递归函数
如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。
简单理解:函数内部自己调用自己, 这个函数就是递归函数
递归函数的作用和循环效果一样
由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件 return
// 求 1 * 2 *3 ... * n 阶乘
function fn(n){
if(n==1) {return 1;}
return n*fn(n-1)
}
console.log(fn(3));
<script>
// 利用递归函数求斐波那契数列(兔子序列) 1、1、2、3、5、8、13、21...
// 用户输入一个数字 n 就可以求出 这个数字对应的兔子序列值
// 我们只需要知道用户输入的n 的前面两项(n-1 n-2)就可以计算出n 对应的序列值
function fn(){
if(n==1||n==2){
return 1;
}
return fn(n-1)+fn(n-2)
}
</script>
9.浅拷贝和深拷贝
- 浅拷贝只是拷贝一层, 更深层次对象级别的只拷贝引用.
- 深拷贝拷贝多层, 每一级别的数据都会拷贝.
- Object.assign(target, ...sources) es6 新增方法可以浅拷贝
浅拷贝更深对象级别的数据,修改数据会影响拷贝和被拷贝的数据
// 深拷贝拷贝多层, 每一级别的数据都会拷贝.
var obj = {
id: 1,
name: 'andy',
msg: {
age: 18
},
color: ['pink', 'red']
};
var o = {};
// 封装函数
function deepCopy(newobj, oldobj) {
for (var k in oldobj) {
// 判断我们的属性值属于那种数据类型
// 1. 获取属性值 oldobj[k]
var item = oldobj[k];
// 2. 判断这个值是否是数组
if (item instanceof Array) {
newobj[k] = [];
deepCopy(newobj[k], item)
} else if (item instanceof Object) {
// 3. 判断这个值是否是对象
newobj[k] = {};
deepCopy(newobj[k], item)
} else {
// 4. 属于简单数据类型
newobj[k] = item;
}
}
}
deepCopy(o, obj);
二、正则表达式
正则表达式( Regular Expression )是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。
正则表通常被用来检索、替换那些符合某个模式(规则)的文本,例如验证表单:用户名表单只能输入英文字母、数字或者下划线, 昵称输入框中可以输入中文(匹配)。此外,正则表达式还常用于过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等 。
1.创建正则表达式
在 JavaScript 中,可以通过两种方式创建一个正则表达式
通过调用 RegExp 对象的构造函数创建
var 变量名 = new RegExp(/表达式/);
通过字面量创建
var 变量名 = /表达式/;
2.测试正则表达式 test
test() 正则对象方法,用于检测字符串是否符合该规则,该对象会返回 true 或 false,其参数是测试字符串。
regexObj.test(str)
1. regexObj 是写的正则表达式2. s tr 我们要测试的文本3. 就是检测 str 文本是否符合我们写的正则表达式规范 .
3.正则表达式的组成
一个正则表达式可以由简单的字符构成,比如 /abc/,也可以是简单和特殊字符的组合,比如 /ab*c/ 。其中特殊字符也被称为元字符,在正则表达式中是具有特殊意义的专用符号,如 ^ 、$ 、+ 等
特殊字符非常多,可以参考:正则测试工具: 在线正则表达式测试
- 边界符:用来提示字符所处的位置,主要有两个字符
如果 ^ 和 $ 在一起,表示必须是精确匹配
- 字符类:字符类表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内
- [] 方括号
- [-] 方括号内部 范围符- :方括号内部加上 - 表示范围
- [^] 方括号内部 取反符^:方括号内部加上 ^ 表示取反,只要包含方括号内的字符,都返回 false
- 字符组合:方括号内部可以使用字符组合
- 量词符:量词符用来设定某个模式出现的次数
- 预定义类:指的是某些常见模式的简写方式
4.正则表达式替换
replace() 方法可以实现替换字符串操作,用来替换的参数可以是一个字符串或是一个正则表达式
stringObject.replace(regexp/substr,replacement)
1. 第一个参数 : 被替换的字符串 或者 正则表达式2. 第二个参数 : 替换为的字符串3. 返回 值是一个替换完毕的新字符串
正则表达式参数
/表达式/[switch]
switch(也称为修饰符) 按照什么样的模式来匹配. 有三种值:
- g:全局匹配
- i:忽略大小写
- gi:全局匹配 + 忽略大小写