深入理解this机制系列第三篇——箭头函数
2016-08-04 19:29
627 查看
×
目录
[1]痛点 [2]解决 [3]基本用法[4]回调函数[5]注意事项
如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分
如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来
由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号
【2】箭头函数不可以当作构造函数,也就是不可以使用new命令,否则会报错
【3】箭头函数中不存在arguments对象
this机制系列介绍完了。最重要的还是第一篇this机制的绑定原则,第二篇this机制的优先级属于要点,而本篇则是拓展部分。如有不妥之处,欢迎交流
以上
// var all = document.getElementById('cnblogs_post_body').children;
var select = [];
for(var i = 1; i < all.length; i++){
if(all[i].getAttribute('id')){
if(all[i].getAttribute('id').match(/anchor\d+$/)){
select.push(all[i]);
}
}
}
var wheel = function(e){
e = e || event;
var data;
if(e.wheelDelta){
data = e.wheelDelta;
}else{
data = -e.detail * 40;
}
for(var i = 0; i < select.length; i++){
if(select[i].getBoundingClientRect().top > 0){
return;
}
if(select[i].getBoundingClientRect().top <= 0 && select[i+1]){
if(select[i+1].getBoundingClientRect().top > 0){
change(oCon.children[i+2])
}
}else{
change(oCon.children[select.length+1])
}
}
}
document.body.onmousewheel = wheel;
document.body.addEventListener('DOMMouseScroll',wheel,false);
var oCon = document.getElementById("content");
var close = oCon.getElementsByTagName('span')[0];
close.onclick = function(){
if(this.innerHTML == '显示目录'){
this.innerHTML = '×';
this.style.background = '';
oCon.style.border = '2px solid #ccc';
oCon.style.width = '';
oCon.style.height = '';
oCon.style.overflow = '';
oCon.style.lineHeight = '30px';
}else{
this.innerHTML = '显示目录';
this.style.background = '#3399ff';
oCon.style.border = 'none';
oCon.style.width = '60px';
oCon.style.height = '30px';
oCon.style.overflow = 'hidden';
oCon.style.lineHeight = '';
}
}
for(var i = 2; i < oCon.children.length; i++){
oCon.children[i].onmouseover = function(){
this.style.color = '#3399ff';
}
oCon.children[i].onmouseout = function(){
this.style.color = 'inherit';
if(this.mark){
this.style.color = '#3399ff';
}
}
oCon.children[i].onclick = function(){
change(this);
}
}
function change(_this){
for(var i = 2; i < oCon.children.length; i++){
oCon.children[i].mark = false;
oCon.children[i].style.color = 'inherit';
oCon.children[i].style.textDecoration = 'none';
oCon.children[i].style.borderColor = 'transparent';
}
_this.mark = true;
_this.style.color = '#3399ff';
_this.style.textDecoration = 'underline';
_this.style.borderColor = '#2175bc';
}
// ]]>
目录
[1]痛点 [2]解决 [3]基本用法[4]回调函数[5]注意事项
前面的话
this机制与函数调用有关,而作用域则与函数定义有关。有没有什么是可以将this机制和作用域联系起来的呢?本文将介绍ES6新增的内容——箭头函数痛点
对于闭包的痛点在于,闭包的this默认绑定到window对象,但又常常需要访问嵌套函数的this,所以常常在嵌套函数中使用var that = this,然后在闭包中使用that替代this,使用作用域查找的方法来找到嵌套函数的this值var a = 0; function foo(){ function test(){ console.log(this.a); } return test; }; var obj = { a : 2, foo:foo } obj.foo()();//0
var a = 0; function foo(){ var that = this; function test(){ console.log(that.a); } return test; }; var obj = { a : 2, foo:foo } obj.foo()();//2
解决
而箭头函数的出现就可以很好的解决该问题。箭头函数根据当前的词法作用域而不是根据this机制顺序来决定this,所以,箭头函数会继承外层函数调用的this绑定,而无论this绑定到什么var test = () => { console.log(this.a); } //形式上等价于 var test = function(){ console.log(this.a); } //实质上等价于 function fn(){ var that = this; var test = function(){ console.log(that.a); } }
var a = 0; function foo(){ var test = () => { console.log(this.a); } return test; }; var obj = { a : 2, foo:foo } obj.foo()();//2
基本用法
ES6允许使用“箭头”(=>)定义函数,一般称为胖箭头var f = v => v; console.log(f(1));//1 //等同于 var f = function(v) { return v; }; console.log(f(1));//1
如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分
var f = () => 5; // 等同于 var f = function () { return 5 }; var sum = (num1, num2) => num1 + num2; // 等同于 var sum = function(num1, num2) { return num1 + num2; };
如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来
var sum = (num1, num2) => { var restult = num1 + num2; return result; }
由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号
var getTempItem = id => ({ id: id, name: "Temp" });
回调函数
箭头函数最常用于回调函数,如事件处理器或定时器中function foo() { setTimeout(() => { console.log( this.a ); },100); } var obj = { a: 2 }; foo.call( obj ); // 2
//等价于 function foo() { var that = this; setTimeout( function(){ console.log( that.a ); }, 100 ); } var obj = { a: 2 }; foo.call( obj ); // 2
注意事项
【1】this在箭头函数中被绑定,4种绑定规则中的无论哪种都无法改变其绑定var a = 0; function foo(){ var test = () => { console.log(this.a); } return test; }; var obj1 = { a : 1, foo:foo } var obj2 = { a : 2, foo:foo } obj1.foo()();//1 var bar = foo.call(obj1); //由于上一条语句已经把this绑定到obj1上,且无法修改。所以本条语句call(obj2)无效,返回的值是obj1.a的值1 bar.call(obj2);//1
【2】箭头函数不可以当作构造函数,也就是不可以使用new命令,否则会报错
var foo = () =>{return 1;} foo();//1 var obj = new foo();//Uncaught TypeError: foo is not a constructor
【3】箭头函数中不存在arguments对象
var foo = () =>{ console.log(arguments);//Uncaught ReferenceError: arguments is not defined return 1; } foo();
最后
虽然箭头函数可以把作用域和this机制联系起来,但是却容易混淆,使代码难以维护。应该在作用域和this机制中二选一,否则它们就真的汇成一锅粥了。或者只使用词法作用域,或者只使用this机制,必要时使用bind()。尽量避免使用that=this和箭头函数this机制系列介绍完了。最重要的还是第一篇this机制的绑定原则,第二篇this机制的优先级属于要点,而本篇则是拓展部分。如有不妥之处,欢迎交流
以上
// var all = document.getElementById('cnblogs_post_body').children;
var select = [];
for(var i = 1; i < all.length; i++){
if(all[i].getAttribute('id')){
if(all[i].getAttribute('id').match(/anchor\d+$/)){
select.push(all[i]);
}
}
}
var wheel = function(e){
e = e || event;
var data;
if(e.wheelDelta){
data = e.wheelDelta;
}else{
data = -e.detail * 40;
}
for(var i = 0; i < select.length; i++){
if(select[i].getBoundingClientRect().top > 0){
return;
}
if(select[i].getBoundingClientRect().top <= 0 && select[i+1]){
if(select[i+1].getBoundingClientRect().top > 0){
change(oCon.children[i+2])
}
}else{
change(oCon.children[select.length+1])
}
}
}
document.body.onmousewheel = wheel;
document.body.addEventListener('DOMMouseScroll',wheel,false);
var oCon = document.getElementById("content");
var close = oCon.getElementsByTagName('span')[0];
close.onclick = function(){
if(this.innerHTML == '显示目录'){
this.innerHTML = '×';
this.style.background = '';
oCon.style.border = '2px solid #ccc';
oCon.style.width = '';
oCon.style.height = '';
oCon.style.overflow = '';
oCon.style.lineHeight = '30px';
}else{
this.innerHTML = '显示目录';
this.style.background = '#3399ff';
oCon.style.border = 'none';
oCon.style.width = '60px';
oCon.style.height = '30px';
oCon.style.overflow = 'hidden';
oCon.style.lineHeight = '';
}
}
for(var i = 2; i < oCon.children.length; i++){
oCon.children[i].onmouseover = function(){
this.style.color = '#3399ff';
}
oCon.children[i].onmouseout = function(){
this.style.color = 'inherit';
if(this.mark){
this.style.color = '#3399ff';
}
}
oCon.children[i].onclick = function(){
change(this);
}
}
function change(_this){
for(var i = 2; i < oCon.children.length; i++){
oCon.children[i].mark = false;
oCon.children[i].style.color = 'inherit';
oCon.children[i].style.textDecoration = 'none';
oCon.children[i].style.borderColor = 'transparent';
}
_this.mark = true;
_this.style.color = '#3399ff';
_this.style.textDecoration = 'underline';
_this.style.borderColor = '#2175bc';
}
// ]]>
相关文章推荐
- 深入理解javascript函数进阶系列第三篇——函数节流和函数防抖
- 深入理解JavaScript系列(2) 揭秘命名函数表达式
- 深入理解JavaScript系列(2):揭秘命名函数表达式
- 深入理解JavaScript系列(4):立即调用的函数表达式
- 深入理解JavaScript系列(2):揭秘命名函数表达式
- 深入理解JavaScript系列(4):立即调用的函数表达式
- 深入理解JavaScript系列(2) 揭秘命名函数表达式
- 深入理解JavaScript系列(2):揭秘命名函数表达式
- 深入理解JavaScript系列(2):揭秘命名函数表达式
- 深入理解JavaScript系列(2):揭秘命名函数表达式
- 深入理解JavaScript系列(4):立即调用的函数表达式
- 深入理解JavaScript系列(15):函数(Functions)
- 深入理解JavaScript系列(15):函数(Functions)
- 深入理解JavaScript系列(4):立即调用的函数表达式
- 深入理解JavaScript系列(4):立即调用的函数表达式
- 深入理解JavaScript系列(2):揭秘命名函数表达式
- 深入理解JavaScript系列(15) 函数(Functions)
- 深入理解JavaScript系列(2):揭秘命名函数表达式
- 深入理解JavaScript系列(15):函数(Functions)
- 深入理解JavaScript系列(2):揭秘命名函数表达式