javascript中的一般函数与ES6的箭头函数对比,以及this指向问题的深度理解

3 篇文章 0 订阅
3 篇文章 0 订阅

关于this的指向问题,老外有文章写得非常棒,在看了老外的文章
并结合自己的想法再修改此篇文章

一 、基本概念

  • 本文定义的一般函数 单纯 指的是js原生函数(ES5函数)
  • 同时ES5中的作用域只有全局作用域(window)以及 函数体作用域
  • (也就是说{}本身在ES5中没有作用域的概念)
  • 本文箭头函数 是建立在ES6环境中的特殊函数 ,因为箭头函数空有一生功夫(可调用,可执行),却缺乏内涵(使用空间),这个概念本来就很奇特

二、等价公式

1.js最简单的一般函数调用

   function a(i){
       return i
   }
   console.log(a(1)) // ======>   1

2.ES6箭头函数调用,

	let a = i => i;
	console.log(a(2))
值得注意的是以上两者在包裹了{}的函数体中,没有return 就相当于 return undefined
let a3 = i => {i};
console.log(a3(1)); // undefined 
而 
let a4 = i=>i; 默认是返回i的
console.log(a4(1)); // 1

函数keli化

1.js中的一般函数 ---- 柯里函数

  • 其实质就是一单个参数作为函数的输入,最后输出一个函数
	function do1(a){
	    console.log("a",a) //1.a 6
	    return function(b){
	        console.log("b",b)//2.b 2
	        return a+b
	    }
	}
	console.log(do1(6)(2))//8

2.ES6中箭头函数等价函数

	let do2 = a=>b=>a+b;
	console.log(do2(3)(7)) // 10

2.1 keli进阶

1. js一般化 柯里变形

	function do2(a){
	    return function d3(param){
	        return function d4(param){
	            return param(a)
	        }
	    }
	}

2. ES6 keli等价,

其实质是一般函数中的d3 d4这种函数名没有多大意义
	let do33 = a=>param=>param=>param(a);

三、this 在一般函数与箭头函数之间的终极理解

  • function 中(一般函数(es5函数))的this,是指向调用该function的最近一层的运行时对象;箭头函数 内部是不存在this的(官方说法就是箭头函数本身并没有一般函数的作用域的概念,说白一些,空有一身功夫,可以打拳,但是缺乏内涵),所以在箭头函数中的this本就不属于箭头函数中的
  • this 查找值的次序
  • 先找this指向的命名空间(作用域),然后找到命名空间(作用域)中的属性,
  • {}字典(在js中叫做实例,实例化过的)没有命名空间,
    ** 1.this 指向 的是(.)前面的对象,this不是变量而是对象,只有一般函数里面有this,且this指向的是包裹一般函数的对象
    ** 2.命名空间(函数作用域)的作用是变量访问用的
    ** 3.箭头函数不绑定this
    ** 4.https://www.cnblogs.com/pssp/p/5216085.html
### 例1
let a =1
let obj = {
    a:2,
    b:function(){
        console.log(this)//
    }
}
obj.b()//{a:2,b:}  
// 一般函数中的this指的是obj (.前面的对象的),所以,谁调用b,谁就是this
let bb = obj.b
bb() 
// window bb() 相当于 在模块内部添加一个 var bb = bb(),而bb此时是在window下的
所以
let a =1
let obj = {
    a:2,
    b:function(){
        console.log(this.a)
    }
}
obj.b()//2
let bb = obj.b
bb() // 1 
### this的生产应用
	其实各种监听事件函数(callback)window.addEvent里面写的回调函数里面指定的this
	就是指向window,这也是内部函数中的this为什么会指向window的原因,因为
	一旦函数的里面再嵌套一层函数,层层相扣,最后里面的this满天飞,那么为了最简
	单明了起见,this都会指向window,这也符合外国人比较直接的思维方式,不像中
	国人人那样的复杂性思维!!
let a =1
let obj = {
    a:2,
    b:function(){
        return function(){console.log(this)}//
    }
}
obj.b()()
//Window 是因为obj.b() 相当于输出的是一个函数,类似于上一个例子的
//var bb =obj.b();bb(),而这个函数是绑定到window下的

###  例2.[私有函数](https://blog.csdn.net/JustOneRoad/article/details/7306762)
 [私有变量地址](https://www.cnblogs.com/tianxintian22/archive/2015/12/14/5045017.html)
let obj = {
    a:2,
    b:function(){
        var handle = function(){ //在函数内部定义的变量(包括函数)
            console.log(this)
        }
        handle()
    }
}
obj.b()//window
// 可以发现this指向的是window,相当于函数内部执行了window.handle()
//但是 window中没有handle变量,这是一次性的,在函数内部定义的变量均是私有变量
//js默认会执行
**闭包**

var f = function(){
(function(){console.log(this)})()
}
f() // window
// 私有变量类似于闭包

#### 箭头函数 例1
let a =1
let obj = {
    a:2,
    b:()=>{
        console.log(this)
        //箭头函数的this寻找方法是代码文字级别(非内存空间)的向上查找,
        //不管对象是谁,但是对象没有this属性,不管上下文
        // 可以打开浏览器 F12 输入 this看看会出现什么
	}
}
obj.b()//Window 指的是最上一层的window this

#### 箭头函数 例2

let a =1
let obj = {
a:2,
b:function(){
return ()=>{
console.log(this) // 在this的上一层是函数,而函数本身是有this属性的
}
}
}
obj.b()()//{a:2,b:f}


### 四、 改变this属性

/**

  • 改变this的三大方法(三种方法都可以传一个对象参数,作为this的对象)
  • bind apply call
  • 这三种方法最本质的区别是
  • 1.bind只是绑定this传入函数体中,并不执行函数
  • 2.apply和call在传入函数体中就会默认执行函数
    */
#### 1.bind 并不执行函数的直观试验
let a =2;
let bindFunc = {
    a:1,
    b:function(){
        return (function(){
            console.log(this)//这里的this指的是bindFunc看下方的.之前的对象,如果不bind就直接指向window,因为这是内部函数形式
        }).bind(this)
    }

}
bindFunc.b()//返回函数function () { … }
bindFunc.b()()//{a: 1, b: }
#### 2.apply和call函数的直观试验

let a =2;
let callFunc = {
a:1,
b:function(){
return (function(){
console.log(this)//这里的this指的是bindFunc看下方的.之前的对象,如果不bind就直接指向window,因为这是内部函数形式
}).call(this)
}
}
callFunc.b()//{a: 1, b: }

let a =2;
let applyFunc = {
    a:1,
    b:function(){
        return (function(){
            console.log(this)//这里的this指的是bindFunc看下方的.之前的对象,如果不bind就直接指向window,因为这是内部函数形式
        }).apply(this)
    }
}
applyFunc.b()//{a: 1, b: }


 #### 3.apply与 call传入其他对象,比如window的话

let a =2;
let callFuncW = {
    a:1,
    b:function(){
        return (function(){
            console.log(this)//这里的this指的是bindFunc看下方的.之前的对象,如果不bind就直接指向window,因为这是内部函数形式
        }).call(window)
    }
}
callFuncW.b()//window
let a =2;
let applyFuncW = {
    a:1,
    b:function(){
        return (function(){
            console.log(this)//这里的this指的是bindFunc看下方的.之前的对象,如果不bind就直接指向window,因为这是内部函数形式
        }).apply(window)
    }
}
applyFuncW.b()//window

### 五、高级训练

#### 训练一
var a = 100;
var b = {
    a:1000,
    b:{
        a:1,
        c:{
            getA:function(){
                console.log(this) //{ getA: [Function: getA] }
                console.log(this.a) // undefined
            }
        }
    }
}
b.b.c.getA()
#### 训练二
var a = 100;
var b = {
    a:1000,
    d:()=>{
        console.log(this.a)
    },
    b:{
        a:1,
        d:()=>{
            console.log(this.a)
        },
        c:{
            a:2,
            getA:()=>{
                console.log(this) // window
                console.log(this.a) //  如果 var声明的,并且没有闭包,就直接运行到 a
            }
        }
    }
}

b.b.c.getA() 
b.d()
b.b.d()


#### 训练4

var b = {
a:1000,
d:()=>{
console.log(this.a)
},
b:function(){
var data={
a:1,
d:()=>{
console.log(this.a)
},
c:{
a:2,
getA:()=>{
console.log(this)//{a: 1000, d: ƒ, b: ƒ}
console.log(this.a)//1000
}
}
}
return data
}
}
b.b().c.getA() //


大家有没有作对?
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值