JS函数(二)


一、函数应用

函数本质上是一种对象,可以将其当做普通对象来使用。

1.回调函数

回调,就是回头调用的意思。主函数的事先做完,回头再调用传进来的那个函数。

回调函数的作用:回调函数一般都用在耗时操作上面:因为主函数不用等待回调函数执行完,可以接着执行自己的代码。比如ajax请求,比如处理文件等。

2.作为返回值

我们在作用域链的案例中,就使用到了函数作为返回值的用法

/**
 * 1.函数可以作为参数 回调函数 回头调用 主函数先执行  回调函数再执行
 * 2.函数可以作为返回值 
 */
function foo(x,y,callback){
	console.log(x,y); // 1 2
	callback(3,4)
}
function fn(a,b){
	console.log(a,b)  // 3 4
	return a + b  // 7
}
foo(1, 2, fn)
// foo(1,2,fn,function(){
// })
console.log('---------------------------------------------------');

var arr = [1,2,3,4,5];
Array.prototype.forEach = function(callback){
	for(var i=0;i<this.length;i++){
		callback(this[i])
	}
}
arr.forEach(function(item){
	console.log(item)
})

console.log('---------------------------------------------------');

function A(callback){
	callback();
	console.log('我是主函数')
}
function B(){
	setTimeout(function(){
		console.log('我是回调函数')
	},1000)
}
A(B); //js事件循环 nodejs 面试
setTimeout(function(){
	console.log(1)
},0);
console.log(0);
console.log(2);

console.log('---------------------------------------------------');


// 2.函数可以作为返回值 
function foo(){
	var a = 10;
	return function(){
		console.log(a)
	}
};
foo()
var res = foo();
console.log(foo()); // [Function (anonymous)]
res();  // 调用返回值  10

console.log('---------------------------------------------------');

var a = 10;
function fn() {
  var b = 20
  function bar() {
    console.log(a + b)
  }
  return bar  // 返回值函数
}
var x = fn(),
b = 200;
x();  // 调用返回值

二、闭包

1.简单讲,闭包就是指有权访问另一个函数作用域中的变量的函数。

MDN 上面这么说闭包是一种特殊的对象。它由两部分构成:函数,以及创建该函数的环境。环境由闭包创建时在作用域中的任何局部变量组成。

2.闭包的生成有三个必要条件

  • 函数嵌套函数

  • 内部函数引用了外部函数中的数据(属性、函数)

  • 参数和变量不会被回收

这样就形成了一个不会销毁的函数空间

  • 产生一个闭包

创建闭包最常见方式,就是在一个函数内部创建另一个函数。

3.优点:不会污染变量 变量会被维持缓存

缺点:造成内存泄漏 造成性能问题

4.闭包的作用域链包含着它自己的作用域,以及包含它的函数的作用域和全局作用域。

在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。

所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

5.闭包的用途

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

6.使用闭包的注意点

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露,这是IE的BUG。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。多个子函数的scope都是同时指向父级,是完全共享的。因此当父级的变量对象被修改时,所有子函数都受到影响。

function func() {
  var a = 1, b = 2;
  function closure() {
    return a + b;
  }
  return closure;
}
console.log(func()()); 

console.log('-----------------------------------------------------');

/**
 * 调用一次函数 变量减少一次 
 */
function foo(){
	var a = 10;
	function fn(){
		a--;
		console.log(a)
	}
	return fn
}
var res = foo();
res();//9
res();//8
res();//7

console.log('-----------------------------------------------------');

function sum(){
	var a = 10;
	a--;
	console.log(a)
}
sum();//9
sum();//9
sum();//9
sum();//9
sum();//9
sum();//9

console.log('-----------------------------------------------------');

function f1() {
  var n = 999;
  nAdd = function () { n += 1 }
  function f2() {
    console.log(n);
  }
  return f2;
}
var result = f1();
result();//999
nAdd();
console.log(nAdd()); // undefined
result();//1000

7.闭包中的this指向问题-初体验

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      var name = "window";
			console.log(this)  // window
      var obj = {
        name: "obj",
        say: function () {
					console.log(this.name) // obj
          return function () {
            console.log(this.name); //window
          };
        },
      };
      var x = obj.say();
      x();
    </script>
  </body>
</html>

三、解决全局作用域

/**
 * 1.解决全局作用域 将var改为let let创建自己得局部作用域
 * 2.使用立即执行函数创建局部作用域 
 * 
 */

var arr = [];
for(var i=0;i<5;i++){
	arr[i] = (function(j){
		console.log(j)
	})(i)
}
// 0 1 2 3 4
console.log('----------------------------------------------------');
var arr = []
for(var i = 0; i < 5; i++){
	arr[i] = (function(j){
		console.log(j);
	})(i)
}


// var arr = []
// for (var i = 0; i < 10; i++ ){
// 	arr[i] = i
// 	console.log(arr[i]);
// }

console.log('--------------------------------------------------');

var arr = [];
for(var i=0;i<5;i++){
	arr[i] = (function(j){
		return function(){
			console.log(j)
		}
	})(i)
}
arr[1](); // 1
console.log('--------------------------------------------------');
var arr = []
for (var i = 0; i < 5; i++){
	arr[i] = (function(j){
		return function(){
			console.log(j);
		}
	})(i)
}
arr[3]()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值