1.函数的定义和调用
1.1 函数的定义
1.函数声明方式function
关键字(命名函数)
function fn(){}
2.函数表达式(匿名函数)
var fun = function(){}
3.new Function('参数1','参数2',...)
var f = new Function('a','b')
- 所有函数都是
Function
的实例对象 - 函数也属于对象
1.2 函数的调用
1.普通函数
function fn(){
console.log('hello')
}
//调用
fn() / fn.call()
2.对象的方法
var o = {
sayHi :function (){
console.log('hello')
}
}
//调用
o.sayHi()
3.构造函数
function Star(){}
//调用
new Star()
4.绑定事件函数
btn.onclick = function(){}
//点击按钮即可调用
5.定时器函数
setInterval(function(){},1000)
//定时器自动一秒钟调用一次
6.立即执行函数
(function(){
console.log('hello')
})()
//立即执行函数是自动调用
2.this指向问题
2.1 函数内this的指向
- this的指向通常是调用函数的时候确定的,调用方式的不同决定了this的指向不同
- 一般指向调用者
调用方式 | this指向 |
---|---|
普通函数调用 | window |
构造函数调用 | 实例对象 |
对象方法调用 | 该方法所属对象 |
事件绑定方法 | 绑定事件对象 |
定时器函数 | window |
立即执行函数 | window |
2.2 改变函数内部this的指向
2.2.1 call()
fun.apply(thisArg,arg1,arg2,...)
//本来this的指向是window
function fn(){
console.log('hello')
}
fn() // hello
var o = {
name:'xxx'
}
//改变函数this的指向 让其指向对象o
fn.call(o) //{name:'xxx'}
- 主要用于继承 参考其他博客继承
2.2.2 apply()
- 同样可以改变this的方式
fun.apply(thisArg,[argsArray])
this.Arg:
fun函数运行时指定的this值
argsArray:
传递的值必须包含在数组里
- 与call的区别主要在于传递参数的方式有所不同
- 主要用于数组
//比如可以利用apply借助于数学内置对象求最大值
var arr = [1,2,3,6,5,9,5]
Math.max.apply(Math,arr) //9
2.2.3 bind()
- bind()不会调用原来的函数,但是能改变函数内部this指向
fun.bind(thisArg,arg1,arg2,...)
- 返回由指定的this值和初始化参数改造的
原函数拷贝
//本来this的指向是window
function fn(){
console.log('hello')
}
fn() // hello
var o = {
name:'xxx'
}
//改变函数this的指向 让其指向对象o
//fn.bind(o) //不会执行
var f = fn.bind(o) //拷贝
f() //{name:'xxx'}
- 开发用的最多
- 不想立即调用 又想改变函数内部this指向
- 有个按钮 点击就禁用 三秒后开启
var btn = document.querySelector('button')
btn.onclick = function(){
this.disabled = true //this指向的是btn这个按钮
setTimeout(function(){
//this.disabled = false 定时器函数里面的this指向的是wiindw 无法生效
this.disabled = false
}.bind(this),3000) //需要在定时器函数外部改变this的指向 此时this指向的是btn
}
2.3 总结
相同点:
都可以改变函数内部的this指向
区别点:
- call 和apply会调用函数,并且改变函数内部this指向
- call 和apply传递的参数不一样, call传递参数arg1, arg2…形式,apply 必须数组形式[arg]
- bind 不会调用函数,可以改变函数内部this指向
主要应用场景:
- call经常做继承
- apply经常跟数组有关系 比如借助于数学对象实现数组最大值最小值
- bind 不调用函数,但是还想改变this指向,比如改变定时器内部的this指向
3.高阶函数
- 函数可以作为参数传递
- 将函数作为返回值输出
- 典型:回调函数
4.闭包**
4.1 变量作用域
变量根据作用域的不同分为两种:全局变量和局部变量。
函数内部可以使用全局变量。
函数外部不可以使用局部变量。
当函数执行完毕,本作用域内的局部变量会销毁。
4.2 什么是闭包?
- 一个
函数
- 有权访问另一个函数作用于中的变量
- 典型的高阶函数
- 立即执行函数也称为小闭包因为立即执行函数里面的任何一个函数都可以使用它的i这变量
//fn()为闭包函数 由于fun()访问了num而产生闭包
function fn(){
var num = 10
function fun(){
console.log(num)
}
fun()
}
fn() //10
4.3 闭包的作用
- 如何在 fn() 函数外的作用域下访问 fn() 中的局部变量
num
呢?
function fn() {
var num = 10;
// function fun() {
// console.log(num);
// }
// return fun;
return function () {
console.log(num);
}
}
var f = fn(); //相当于将fun()赋值给f()
f();
主要作用: 延伸变量的作用范围
4.浅拷贝和深拷贝**
- 浅拷贝:只拷贝一层,如果存在对象中的对象,只保存对象的地址指向拷贝对象的对象,若进行更改,会将拷贝对象的值也进行更替
- 深拷贝:拷贝多层,每一级别的数据都会拷贝,会重新开辟内存空间
Object.assign(target,source)
: 可以实现浅拷贝
var obj={
name:'Tom',
msg:{
age:18
}
}
var o={};
for(var k in obj){
o[k]=obj[k];
}
// 浅拷贝
o.msg.age=20;
console.log(o); //o.msg.age=20;
console.log(obj); //obj.msg.age=20;
深拷贝可运用递归
思想:
// 封装函数
function deepCopy(newObj,oldObj){
for(var k in oldObj){
var item = oldObj[k];
if(item instanceof Array){ //数组先判断 因为数组也属于对象
newObj[k]=[];
deepCopy(newObj[k],item)
}
else if(item instanceof Object){
newObj[k]={};
deepCopy(newObj[k],item)
}
else{
newObj[k]=oldObj[k];
}
}
}
//深拷贝
deepCopy(o,obj);
o.msg.age=20;
console.log(o); //o.msg.age=20;
console.log(obj); // obj.msg.age=18;
5.正则表达式
- 见另一篇博客【JavaScript】正则表达式主要知识点总结