函数进阶及闭包

一、函数进阶

让我们先回忆下函数是怎样定义的?

1.1、函数的定义

  • 方式一 关键字定义
function fn(){
	//代码块
}
  • 方式二 匿名函数法
var fn = function(){
	//代码块
}
  • 方式三 构造函数法
var f = new Function('a', 'b', 'console.log(a + b)'); 
// 'a','b',为形参,console.log(a + b)为函数体
// 这里Function中,F是大写的
f(1, 2); 
  • 注意

(1)Function 里面参数都必须是字符串格式;
(2)构造函数法执行效率低,也不方便书写,因此较少使用;
(3)所有函数都是 Function 的实例(对象);
(4)函数也属于对象。

1.2、函数的调用

  • 普通函数调用
function fn() { 
	console.log('lll'); 
}
//调用
fn();
  • 对象的方式
var o = { 
	sayHi: function() { 
		console.log('111'); 
		} 
}
//调用
o.sayHi()
  • 构造函数式
function Star() {
}; 
//调用
new Star();
  • 绑定事件函数的三种调用方式
// 点击按钮就可以调用这个函数
btn.onclick = function() {}; 

// 点击了按钮就可以调用这个函数
function add() {}; 
btn.onclick = add; 

// 点击了按钮就可以调用这个函数
var add = function(){} 
btn.onclick = add; 

1.3、立即调用函数

  • 概念

立即调用函数(自调用函数),IIFE,是一个定义的同时执行的函数。

// 基本形式
(function() { 
	console.log('111'); 
})();
  • 立即执行函数获取外部变量
var x= 10 
(function(a) { 
	console.log(a++); 
})(x);// 内部获取x的值
  • 立即调用函数的局部作用域问题
(function () { 
	var name = "Barry"; 
})(); // 此时,无法从外部访问变量 name 
  • 实例
for (var i = 1; i < 5; i++) {
     setTimeout(function () {
          console.log(i++);;
     }, 200)
}

// 由于setTimeout是异步代码,所以先执行for循环,
// 然后进入异步代码内部执行
console.log(i);  //5
console.log('over'); //  over 5 6 7 8 

二、this

2.1、this指向性问题

调用方式this指向
普通调用函数window
构造函数调用实例对象
对象方法调用所属对象
事件绑定方法绑定事件对象
定时器函数window
立即调用函数window

2.2、改变函数内部this指向

正常情况下:

// 函数内部this指向window
function fn(a,b){
      console.log(this); //window
      console.log(a/b);   //2     
}

fn(10,5);

那如果想要改变this的指向呢?
以下介绍几种方法!

  • call()
function fn(a,b){
      console.log(this.sex); //女
      console.log(a/b);   //2     
}

var obj = {
    sex:'女'
}

call()
// 此时.this的指向已经改变
fn.call(obj,10,5)
  • apply()
apply()
// 注意,这里参数用数组包起来
fn.apply(obj,[10,5])
  • bind()
// bind()方法并不会立即执行函数,而是先返回一个函数对象
var t = fn.bind(obj,10,5);
t()

三、闭包

在这之前,我们先了解下什么是高阶函数?

3.1、高阶函数

高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。

function fn(){
	return function(){};
}
// 把函数作为返回值
fn(); //此时,fn()结果为function(){};

3.2、闭包

通俗来讲,就是在一个函数内部再定义一个函数,内部函数使用到外部函数的局部变量,并且外部函数返回值是内部函数。

是不是有点蒙,其实就是满足三个条件:

(1)函数内部嵌套函数;
(2)内部函数用到外部函数的变量;
(3)外部函数返回值为内部函数。

// 闭包
function out1(){
      var a = 111;
      function in2(){
          return a;
      }
      return in2;
}

var f1 = out1(); //f1等于in2()
var f2 = f1() //f2 等于in2的返回值 即a

我们知道,正常情况下在全局作用域下是无法访问局部变量的,闭包却可以解决这种境况。

3.3、闭包的作用

function Foo() {
     var i = 0;
     return function () {
          console.log(i++);
     }
}

var f1 = Foo();
f1();//0
f1();//1
f1();//2
f1();//3

就是可以在全局位置访问到局部的变量

3.4、用闭包解决选项卡问题

// 闭包实现选项卡功能
    var oBut = document.querySelectorAll('button');
    var oDiv = document.querySelectorAll('div');

    for (var i = 0; i < oBut.length; i++) {
        (function (n) {
            oBut[n].onclick = function () {
                for(var j=0;j<oDiv.length;j++){
                    oBut[j].className = '';
                    oDiv[j].className = '';
                }
                oBut[n].className = 'b1';
                oDiv[n].className = 'd1';
            }
        })(i)//将i传递给内部事件函数,保存i的值
    }

3.5、闭包实现点击按钮自加1

// 点击按钮自加1
    var oBut = document.querySelector('button');
    oBut.onclick = function(){
        f();
    }

    function f1(){
        var i =0;
        return function(){
            console.log(i++);           
        }
    }
    var f = f1()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值