This in JavaScript

栏目: JavaScript · 发布时间: 5年前

内容简介:这篇文章我们来理解下js中的在开始之前,我们先定义几个规则

这篇文章我们来理解下js中的 this 关键字

在开始之前,我们先定义几个规则

  1. 函数作为方法调用, 也就是用 . 的方式
  2. new 的方式
  3. applycallbind 的方式
  4. 函数作为自由函数调用

第一种规则,函数作为方法调用

this 指向的就是调用方法的对象

let obj = {
    name: 'len',
    sayName: function() {
        console.log(this)
    }
}

obj.sayName() // { name: 'len', sayName: [Function: sayName] }
复制代码

第二种规则

this 指向的就是新创建的对象,我们都知道,使用 new 关键字的时候,会创建一个新的对象

let obj = {
    name: 'len',
    sayName: function() {
        console.log(this)
    }
}

new obj.sayName() // sayName {}
复制代码

第三种规则

这时候, this 指向的就是调用bind,apply,call方法的第一个参数(下面例子中的 obj )

function fn() {
    console.log(this)
}

let obj = {
    value: 5
}

let boundFn = fn.bind(obj)

boundFn() // { value: 5 }
fn.call(obj) // { value: 5 }
fn.apply(obj) // { value: 5 }
复制代码

第四种规则

在浏览器中, 这时候 this 指向的就是就是window对象

function foo() {
    console.log(this)
}

foo() // Window{}
复制代码

规则中的组合情况

const obj = {
    value: 'hi',
    printThis: function() {
        console.log(this)
    }
}
const print = obj.printThis

// 规则1,this指向的就是obj
obj.printThis()  // {value: 'hi', printThis: f} 
// 规则4,this指向的就是Window
print() // Window {}
复制代码
const obj1 = {
    value: 'hi',
    printThis: function() {
        console.log(this)
    }
}

const obj2 = {value: 17}

// 规则1和3的组合, 规则3的优先级大于规则1
obj1.print.call(obj2) // {value: 17}

// 规则1和规则2的组合,规则2的优先级大于规则1
new obj1.print() // {}
复制代码

闭包中的this

var name = 'window'
let object = {
    name: 'len',
    sayName: function() {
        return function() {
            return this.name
        }
    }
}

console.log(object.sayName()()) // window
复制代码

上面为什么打印window呢?我们拆开来看

let firsr = object.sayName()
first() // 这是作为单独函数调用的,也是就是上面的'规则4',所以this自然就指向window了
复制代码

es6箭头函数的this

箭头函数没有自己的this,请看:

// es6
function foo() {
    setTimeout(() => {
        console.log(this)
    })
}

// es5
function foo() {
    var _this = this
    setTimeout(function() {
        console.log(_this)
    }, 1000)
}

foo() // Window{}
new foo() // foo{}
这样就又回到了上面的规则了。
复制代码

上面es5代码是我用在线babel编译es6代码得到的。从上面我们可以看出,箭头函数是没有自己的this的,它实际上是保存了父级作用域的this,然后在箭头函数里面调用的都是父级作用域的this。也正是因为箭头函数没有this,所以自然而然我们就不能使用call,apply,bind来改变this的指向了。

最后,来个面试题

class Animal() {
    constructor(type) {
        this.type = type
    }
    
    say(val) {
        setTimeout(() => {
          console.log(this);
          console.log(this.type + " says " + val);
        }, 1000)
    }
}

// es6的class里面的方法都是定义在prototype上的
console.log(Animal.prototype) // 在浏览器中 {constructor: f, say: f}

const animal = new Animal('animal')
animal.say('hi') // 1s later console log "Animal{type: 'animal'}" and "animal says hi"
复制代码

我们将上面的改动一下

class Animal() {
    constructor(type) {
        this.type = type
    }
    
    say(val) {
        // 这里没有使用箭头函数,这里的setTimeout形成了一个闭包,this指向的是window
        setTimeout(function() {
          console.log(this);
          console.log(this.type + " says " + val);
        }, 1000)
    }
}

const animal = new Animal('animal')
animal.say('hi') // Window {} / undefined says hi
复制代码

总结: js中的this还是挺好理解。只要自己用心去理解,相信你可以做到的。好了,就到这了,如果觉得文章有什么问题,可以在下面留言探讨下。毕竟都是在学习,没有不出错的。谢谢理解!


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Designing Programmes

Designing Programmes

Karl Gerstner / Springer Verlag / 2007 / $499.00

Karl Gerstnera (TM)s work is a milestone in the history of design. One of his most important works is Designing Programmes, which is presented here in a new edition of the original 1964 publication. I......一起来看看 《Designing Programmes》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具