作用域、作用域链精解,立即执行函数,闭包

作用域精解
  • [[scope]]:每个javascript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供javascript引擎存取,[[scope]]就是其中一个。[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合。
  • 作用域链:[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。
  • 运行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁。
  • 查找变量:从作用域链的顶端依次向下查找。
function a() {
	function b() {
		var b = 234;
	}
	var a =123;
	b();
}
var glob = 100;
a();
b  scope chain作用域链 
[[scope]]作用域链 0b的AO
   1a是AO
   2GO

闭包

当内部函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄漏。

function a() {
	function b() {
		var bbb = 234;
		document.window(aaa);
	}
	var aaaa =123;
	return b;
}
var glob = 100;
var demo = a();
demo();
//内部的函数通过return保存到外部一定形成闭包
function a() {
	var num = 100;
	function b() {
		num ++;
		console.log(num);
	}
	return b;
}
var demo = a();
demo();//101
demo();//102
//b被返回时,还没有被执行

闭包的作用

实现公有变量
eg:函数累加器
可以做缓存(存储结构)
eg:eater
可以实现封装,属性私有化
eg:Person();
模块化开发,防止污染全局变量

//函数累加器
function add() {
	var count = 0;
	function demo() {
		count ++;
		console.log(count);
	}
	return demo;
}
var counter = add();
counter();
counter();
counter();
//一对二的闭包
function test() {
	var num = 100;
	function a() {
		num ++;
		console.log(num);
	}
	function b() {
		num --;
		console.log(num);
	}
	return [a, b];
}
var myArr = test();
myArr[0]();//101
myArr[1]();//100
//存储结构
function eater() {
	var food = "";
	var obj = {
		eat : function () {
			console.log("i am eating " + food);
			food = "";
		},
		push : function (myFood) {
			food = myFood;
		}
	}
	return obj;
}
var eater1 = eater();
eater1.push('banana');
eater1.eat();//banana

function test() {
	var food = "apple";
	var obj = {
		eatFood : function () {
			if(food != "") {
				console.log("i am eating " + food);
				food = "";
			}else{
				console.log("empty!")
			}
		},
		pushFood : function (myFood) {
			food = myFood;
		}
	}
	return obj;
}
var person = test();
person.eatFood();//i am eating apple
person.eatFood();//empty!
person.pushFood('banana');
person.eatFood();//banana
//多个函数被保存到外面形成闭包,用的是同一个food

立即执行函数

定义:此类函数没有声明,在一次执行过后即释放。适合做初始化工作。

//针对初始化功能的函数
(function (){
	var a = 123;
	var b = 234;
	console.log(a + b);
}())
(function (a, b, c){
	console.log(a + b + c * 2);
}(1, 2, 3))
//可以加参数
var num = (function (a, b, c){
	var d = a + b + c * 2 - 2;
	return d;
}(1, 2, 3)) 
//返回值
//(function (){}());  W3C建议第一种
//(function (){})();
//只有表达式才能被执行符号执行
//能被执行符号执行的表达式,名字就会被忽略
var test = function () {
	console.log('a');
}();
//执行完之后再打印test,显示undefined
+ function test() {
	console.log('a');
}();
//加正负号叹号就变成表达式,放弃表达式名字
//加括号把函数声明变成表达式,放弃名字,就变成立即执行函数(function (){}()); 
function test(a, b, c, d) {
	console.log(a + b + c + d);
}(1, 2, 3, 4);
//系统不报错也不执行,系统将最后的括号和上面的函数看成是2个东西
function test() {
	var arr = [];
	for(var i = 0; i < 10; i++) {
		(function(j) {
			arr[j] = function () {
			console.log(j);
			}
		}(i));
	}
	return arr;
}
var myArr = test();
for(var j = 0; j < 10; j++) {
	myArr[j]();
}
//十个函数对应十个函数

练习

1.写一个方法,求一个字符串的字节长度。

function retByteslen(target) {
	var count = target.length;
	for(var i = 0; i < target.length; i++) {
		if(target.charCodeAt(i) > 255) {
			count ++;
		}
	}
	console.log(count);
}
retByteslen('sadfasdfs对方是否');
//再简化
function retByteslen(target) {
	var count,
		len;
	count = len = target.length;
	for(var i = 0; i < len; i++) {
		if(target.charCodeAt(i) > 255) {
			count ++;
		}
	}
	console.log(count);
}
retByteslen('sadfasdfs对方是否');
//逗号操作符,先看前面的表达式先计算,再看后面的表达式计算,把后面的表达式计算结果返回数据

var a = (1 - 1, 1 + 1);//2

2.写出下面程序的执行结果:

var f = (
	function f() {
		return "1";
	},
	function g() {
		return 2;
	}

)();
typeof f;//number

3.写出下面程序的执行结果:

var x = 1;
if(function f() {}) {
	x += typeof(f);
}
x;//1undefined
//括号里面的函数变成了表达式,f就没有了,未经声明的f就是个字符串类型的undefined
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值