js BOM DOM部分基础知识学习笔记(3)
JavaScript_this关键字
目录
JavaScript_this关键字
事件中的this
对象中的this
JavaScript_函数_闭包概念
如何从外部读取局部变量
闭包的概念
JavaScript_闭包特点
变量的值始终保持在内存中
使用闭包的注意点
JavaScript_闭包应用场景
JavaScript_闭包中的this关键字
事件中的this
监听函数内部的this指向触发事件的那个元素节点
// HTML 代码如下// var btn = document.getElementById('btn');// 写法一btn.onclick = function () { console.log(this.id);};// 写法二btn.addEventListener('click',function (e) { console.log(this.id);},false);
对象中的this
永远指向调用者,而难的就是你是否可以找到调用者
var username = 'sxt';var user = { username:"itbaizhan", getName:function(){ console.log(username);//username == window.username console.log(this.username);//相当于user.username }}user.getName();//sxt itbaizhan
JavaScript_函数_闭包概念
闭包(closure)是 Javascript 语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现
理解闭包,首先必须理解变量作用域
变量的作用域
要理解闭包,首先必须理解Javascript特殊的变量作用域
变量的作用域无非就是两种
- 全局变量
- 局部变量
var n = 100;function getNum(){ console.log(n);}getNum(); // 100
另一方面,在函数外部自然无法读取函数内的局部变量
function getNum(){ var n = 100; num = 10;//没有添加var 就变成了全局作用域}console.log(n); // errorconsole.log(num); // 10
温馨提示
这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量
如何从外部读取局部变量
出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现
那就是在函数的内部,再定义一个函数
function getNum(){ var n = 100; function getN(){ alert(n); // 100 }}
//全局作用域if(true){ var age = 10;}//在js中以完整的函数作为作用域分割点
既然getN
可以读取getNum
中的局部变量,那么只要把getN
作为返回值,我们不就可以在getNum
外部读取它的内部变量了吗
function getNum(){ var n = 100; function getN(){ console.log(n); } return getN;}var result = getNum();result(); // 100
闭包的概念
上述代码中的getN
函数就是闭包
各种专业文献上的"闭包"(closure)定义非常抽象,很难看懂。我们参考老前辈的理解是:闭包就是能够读取其他函数内部变量的函数
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁
function getName(){ var username = "it"; function innerGetName(){ return username; } return innerGetName; } var result = getName(); var uname = result(); console.log(uname);//it
JavaScript_闭包特点
- 读取函数内部的变量
- 变量的值始终保持在内存中
读取函数内部的变量
function getNum(){ var n = 100; function getN(){ console.log(n); } return getN;}var result = getNum();result(); // 100
变量的值始终保持在内存中
观察多次调用函数,n
的变化
function getNum(){ var n = 100; n++; console.log(n);}getNum(); // 101getNum(); // 101
将n
放入到函数中进行增加,然后观察n
的变化
function getNum() { var n = 100; nAdd = function () { //前面没有var 表示全局函数 n += 1 } console.log(n);}getNum(); // 100nAdd();getNum() // 100
增加闭包,再观察n
的变化
function getNum() { var n = 100; nAdd = function () { n += 1 } function getN() { console.log(n); } return getN;}var result = getNum();result(); // 100nAdd();result(); // 101
使用闭包的注意点
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题
function getNum() { var n = 100; function getN() { n += 1; console.log(n); } return getN;}var result = getNum();result();//101result();//102
JavaScript_闭包应用场景
创建一个函数,声明一个数组,然后向数组中放入一个函数,函数值为i * i
function count() { var arr = []; for (var i = 1; i <= 3; i++) { arr.push(function () { return i * i; }); }//循环结束i = 4 ,之前的i被覆盖 return arr;}var results = count();var f1 = results[0];var f2 = results[1];var f3 = results[2];console.log(f1(),f2(),f3()); // 16 16 16
原因就在于返回的函数引用了变量i
,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i
已经变成了4
,因此最终结果为16
返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量
如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变
function count() { var arr = []; for (var i = 1; i <= 3; i++) { arr.push((function (n) { return function () { return n * n;//利用闭包帮我们保存变量 } })(i)); } return arr;}var results = count();var f1 = results[0];var f2 = results[1];var f3 = results[2];f1(); // 1f2(); // 4f3(); // 9