仔细阅读下面的代码,能不能利用changeColor()在点击button时改变<h2>的颜色?
<h2>万紫千红</h2> <button style="color:red" name="change-color">变红</button> <button style="color:blue" name="change-color">变蓝</button> <button style="color:yellow" name="change-color">变黄</button> <script> function changeColor(color) { document.getElementsByTagName('h2')[0].style.color = color; } </script>
我们已经抽象出了函数changeColor(color),注意这个函数是带着参数的。怎么在事件的回调函数里传参呢?(复习)
@想一想@:能不能这样写?
document.getElementsByTagName('button')[0].onclick = changeColor(this.style.color);
复习:事件绑定的应该是一个函数,而不能是函数运行结果(不能传参),怎么办呢?
<button style="color:red" onclick="changeColor(this.style.color)" name="change-color">变红</button>@想一想@:为什么这里的onclick可以直接使用()和this?(复习)可以将行内onclick绑定想象成自带了一个包裹function……
var buttons = document.getElementsByTagName('button');
for (var i = 0; i < buttons.length; i++) { buttons[i].onclick = function () { changeColor(this.style.color);//注意这里使用的是this } }
buttons[i].onclick = changeColor(buttons[i].style.color);
function changeColor(color) { return function () { document.getElementsByTagName('h2')[0].style.color = color; } }
但是,假如你选择了这种方式:
for (var i = 0; i < buttons.length; i++) { buttons[i].onclick = function () { document.getElementsByTagName('h2')[0].style.color = buttons[i].style.color; } }
演示:当事件触发的时候,i 的值为3
@想一想@:为什么呢?
因为事件的绑定和触发是分离的:
怎么破?
for (var i = 0; i < buttons.length; i++) { //绑定时立即执行 buttons[i].onclick = (function (n) { //为了清晰,形参重命名为n //立即执行之后返回的还是函数才行 return function () { //n不要声明在这里,否则…… document.getElementsByTagName('h2')[0].style.color = buttons[n].style.color; } })(i); //利用此时的i }
信息量很大,同学们按这三步进行理解:
我们来看一段更简单的代码:
function luckyStack() { var _price = 986; return function () { return ++_price; } //函数返回了一个函数 } var getPrice = luckyStack();//typeof getPrice alert(`"源栈"培训的价格是每周${getPrice()}元!`);注意,我们再来捋(复习)一遍:
但是,“闭包”出现了!由于:
这就被称之为:闭包。
演示:每调用一次getPrice(),_price均自增一次,说明_price本身一直存在。
关于闭包的定义很多:有的非常宽泛,比如“函数作用域就是闭包”(有道理但可能没意义);有的很学究气,比如
函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包(closure)
不明白这个的定义不要紧。同学们只需要理解:
演示:并理解上文for循环中IIFE形成的闭包
演示:将上述代码改成 let i = 986;
能完美解决上述闭包for循环的问题,让每一个匿名function都绑定了循环时的 i 变量值。参考:MDN,(演示:略)
for (let i = 0; i < buttons.length; i++) {
function foo(x) { var tmp = 3; return function (y) { x = x ? x + 1 : 1; console.log(x + y + tmp); } } var bar = foo(-1); //或者:var bar = foo(1); //或者:var bar = foo(0); bar(10);
function buildList(list) { var result = []; for (vari = 0; i < list.length; i++) { result.push(function () { console.log('item' + i + ': ' + list[i]) }); } return result; } (function() { var fnlist = buildList([1, 2, 3]); for (var i = 0; i < fnlist.length; i++) { fnlist[i](); } })();
多快好省!前端后端,线上线下,名师精讲
更多了解 加: