JavaScript - 函数

Function 类型

每个函数都是 Function 类型的一个实例,与其他引用类型一样具有属性和方法。函数也是对象。所以,函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。

函数中没有重载的概念。
强类型语言中存在重载的概念,但是 JavaScript 是弱类型语言,不存在重载的概念。

何为重载?
比如说,2个一样的函数,后面的函数不会覆盖前面的函数,并且当调用一个函数时,能够全执行对应的函数。

但在 JavaScript 中,如果存在2个相同的函数,那么后面的函数会覆盖掉前面的函数(实际上覆盖了引用第一个函数的变量名)。

function sum(){
	console.log("111");
}
function sum(){
	console.log("222");
}
sum();//222

函数声明和表达式的

函数声明
函数声明的重要特性就是函数声明提升,是指函数名称可以在代码之前执行。

sum();//111
function sum(){
	console.log("111");
}

表达式
但是通过表达式的函数,则必须等到姐解析器执行到所在代码才可以被解释执行。
这种模式创建的函数叫做匿名函数,因为 function 关键字后面没有标识符。

sum1();//报错 TypeError:sum1 is not a function
var sum1 = function(){
	console.log("333");
}

函数内部属性
函数内部有2个特殊对象。argumetns 和 this。arguments 是保存形参到。期中还有一个callee属性。指向 arguments 对象的函数。

arguments.callee指向函数本身。

caller
该属性中保存着调用当前函数的引用,如果是在全局环境下调用的,它的值则是 null。

function outer(){
	inner()
}
function inner(){
	alert(inner.caller);
}
outer(); // 弹出 outer函数的函数体

上面代码中,outer() 调用了 inner(),所以 inner.caller 就指向了 outer(),为了实现更松散的耦合,也可以通过:arguments.callee.caller。

call 和 apply
call和apply方法具有相同的功能,都可以直接改变被执行函数的作用域指向传参指定的新对象,即更改被执行函数的内部指针this的指向。

调用 - 函数.call(apply)(想要this是谁就写谁(不用this时写null),参数1,参数2)
call()方法的第二个参数只能是散的参数。apply()方法的第二个从参数只能是数组的
用途:求最大值 最小值时 类数组转为数组 方法执行。

bind方法
该方法会创建一个函数的实例,它的 this 值会被绑定到传给 bind() 函数。

window.color = "red";
var o  = {
	color: "blue"
}
function sayColor(){
	alert(this.color)
}
var objs = sayColor.bind(o);
objs()//blue

在所有代码执行之前,作用域中就已经存在2个内置对象,Global 和 Math。大多数ECMAscript 实现中都不能直接访问 Global对象,不过,web浏览器提供了 window 对象,全局变量和函数都是 GLobal对象的属性。

闭包

指有权访问另一个函数变作用域中的变量的函数。
创建的闭包方式就是在一个函数中,创建另一个函数。

function fn(){
	let name="33";
	return function(){
	}
}

由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,过度使用闭包函数可能会导致内存占用过多。

闭包和匿名函数中出现的 this 执行 window。

内存泄漏
因为 IE9 之前的版本中,如何闭包的作用域链中保存着一个 HTML 元素,那么就意味着该元素将无法销毁。

function fn(){
	var ele = document.getElementById("id");
	ele.onclick=function(){
		alert(ele.id);
	}
}

上面的代码中,创建了一个 ele 元素事件闭包,而闭包还创建了一个循环引用,由于匿名函数保存了一个对 fn() 活动对象的引用,因此就会导致无法减少 ele 的引用数,只要闭包函数存在(因为要弹出 ele.id ),所以免不了对 ele元素的引用,而 ele.id 又在闭包中,就会对该元素形成循环引用,只要这个闭包存在,对 ele 元素的引用至少是 1 次。所以就会占用内存,永远不会被回收。

解决方案

function fn(){
	var ele = document.getElementById("id");
	var id = ele.id
	ele.onclick=function(){
		alert(id);
	}
	ele =null;
}

上面的代码中,把 ele.id 的一个副本保存在一个变量中,并且在闭包中引用该变量消除了循环引用,但,因为闭包会引用包含函数的整个活动对象,其中包含 ele,即使闭包不直接引用 ele ,包含对象中也会保存着一个引用,因此,有必要 ele 变量值设置为 null。这样就能接触对 DOM 对象的引用了。顺利减少引用数。确保正常回收占用的内存。

总结

  • 将对 HTML 元素的引用赋值给一个变量,变样消除对该元素的引用
  • 由于闭包会引用外部函数的整个活动对象,即使闭包不直接引用 HTML 元素,但外部函数中依旧会保持对该元素的应用(因为 通过 ID 名,类名等获取元素的操作),所以将这个变量赋值 null,就接触了对 DOM 对象的引用。回收占用的内存。

闭包的作用域

闭包的作用域链包含了自己的作用域、包含了函数的作用域和全局作用域。

当函数返回了一个闭包时,这个函数的作用域就会一直在内存中直到闭包不存在。

使用闭包可以模仿块级作用域

创建并立即调用一个函数,这样既可以执行其中的代码,又不会在内存中留下引用。
结果就是函数内部的变量都会被立即销毁。(除非将某些变量赋值给外部的作用域中的变量)。
闭包还可以用于在对象中创建私有变量…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值