目录
函数定义和调用
函数定义的方式
1、函数声明:function关键字;
function 函数名(){}
2、函数表达式(匿名函数);
var 函数名=function(){}
3、new Function();
new Function('参数1','参数2','函数体') //参数必须是字符串形式
var fn=new Function('a','b','console.log(a+b)');
fn();
所有函数都是Function的实例,函数也属于对象,所以函数也有原型对象,实例化函数对象也有对象原型。
函数调用的方式
1、普通函数
2、对象的方法
3、构造函数
4、绑定事件函数
5、定时器函数
6、立即执行函数
this
函数内的this指向
调用方式 | this指向 |
---|---|
普通函数 | window |
构造函数 | 实例化对象 |
对象方法 | 调用方法的对象 |
事件绑定 | 绑定事件的对象 |
定时器函数 | window |
立即执行函数 | window |
改变函数内this指向的三种方式
call()
<script>
var obj={
name='andy'
}
function fn(a,b){
console.log(this);
}
fn.call(obj,1,2); //this指向对象obj
</script>
apply()
函数名.apply(thisArg,[argsArray])
// 调用一个函数,改变this指向,返回值是函数的返回值,传递的值必须包含在数组里
<script>
var obj={
name='andy'
}
function fn(a,b){
console.log(this);
}
fn.apply(obj,[1,2]); //this指向对象obj
</script>
应用:apply的参数必须是数组(伪数组),可以用来求一组数的最大值,比如Math.max(数1,数2,数3…)
<script>
var arr=[1,3,23,22,12];
var max=Math.max.apply(Math,arr); //还是指向Math
</script>
bind()
函数名.bind(thisArg,arg1,arg2...)
// 不会调用函数,返回指定的this值和初始化参数改造的原函数拷贝
<script>
var obj={
name:'xiaoming'
}
function fn(){
console.log(this) //obj对象
}
var f=fn.bind(obj);
console.log(f()); //undefined,函数没有返回值
</script>
严格模式
IE10以上支持,可以应用到在整个脚本或者个别函数中。
在所有语句前放一个特殊语句/在函数体内所有语句前
"use strict";
或者
'use strict';
严格模式和正常模式的script脚本不利于合并,可以将整个脚本文件放在一个立即执行函数中
<script>
(function(){
"use strict";
...
})()
</script>
严格模式下的一些变化
全局变量必须显式声明,不允许不声明就赋值。
不能使用delete删除变量。
构造函数不加new调用,this会报错。
全局作用域的this指向undefined。
对象不允许有重名的属性,函数不允许有重名的参数。
函数声明必须在顶层,不允许在非函数的代码块内声明函数。
高阶函数
对其他函数操作的函数,可以将函数作为参数,或返回一个函数。
<script>
function fn(a,b,callback){
console.log(a+b);
callback&&callback();
}
fn(1,2,function(){
console.log('函数作为参数');
})
</script>
<script>
function fn(){
return function(){}
}
</script>
闭包
变量作用域
函数内部可以使用全局变量,函数外部不可以使用局部变量,函数执行完毕局部变量会被销毁。
闭包closure
指有权访问另一个函数作用域中变量的函数。
闭包主要作用:延伸变量作用范围
<script>
function fun(){
var a=10;
function fn(){
console.log(a); //函数fn访问了另一个函数的局部变量a
}
fn();
}
fun(); //在这里设断点,观察到闭包是fun()
//控制台》》源代码》》一直点击下一步》》作用域中出现“关闭”,就是闭包
//console>>source>>下一步>>scope里出现closure,就是闭包
</script>
被访问的变量所在的函数就是闭包函数
利用闭包得到li的索引
<script>
for(var i=0;i<lis.length;i++){
(function(i){
lis[i].onclick=function(){
console.log(i);
}
})(i);
}
</script>
递归
自己调用自己的函数
<script>
function fn(){
if(num==6){
return; //终止递归条件
}
num++;
fn();
}
fn();
</script>
求1~n的阶乘
<script>
function fn(m){
if(m==1){
return 1;
}
return m*fn(m-1);
}
</script>
斐波那契数列
<script>
function fn(n){
if(n==1 || n==2){
return 1;
}
return fn(n-1)+fn(n-2);
}
</script>
浅拷贝和深拷贝
浅拷贝只复制地址,拷贝对象和原对象指向同一个地址,修改拷贝对象会影响原对象。
<script>
var obj={
id:1,
name:'andy',
msg:{
age:18
}
}
var o={}
for(var k in obj){
o[k]=obj[k];
}
console.log(o); //age:20
o.msg.age=20;
console.log(o); //age:20
console.log(obj); //age:20
//这里是把对象obj的地址直接赋值给o对象,所以更改o的属性值会修改obj
</script>
ES6新增方法实现浅拷贝:Object.assign(拷贝对象,原对象)
深拷贝会创建一个新地址存放拷贝对象,修改拷贝对象不会影响原对象。
<script>
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]=item;
}
}
}
</script>