JS的this指向

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

内容简介:js函数中this是面试官最喜欢考察的,整理一下常用的this指向的知识点。非严格模式和严格模式中this都是指向顶层对象在非严格模式下,普通函数的this指向window

js函数中this是面试官最喜欢考察的,整理一下常用的this指向的知识点。

一、全局上下文

非严格模式和严格模式中this都是指向顶层对象

this.myname = 'xyf'
console.log(this) //Window {myname: 'xyf', …}

二、函数上下文

普通函数

在非严格模式下,普通函数的this指向window

{.line-numbers}
var myname = 'xyf'
var sayName = function(){
    console.log(this === window) // true
    console.log(this.myname) // 'xyf'
}
sayName()

这里的 sayName() 相当于调用了 window.sayName() 。在严格模式下,普通函数的this指向undefined

'use strict'
var myname = 'xyf'
var sayName = function(){
    console.log(this === window) // false
    console.log(this.myname) // 报错,因为this是undefined
}
sayName()

在ES5中,var会给顶层对象中(浏览器是window)添加属性,而使用let则不会。

let myname = 'xyf'
let sayName = function(){
    console.log(this === window) // true
    console.log(this.myname) // undefined
}
sayName()

对象中的函数

对象中的函数this指向对象本身

var myname = 'outside name'
var sayName = function(){
    console.log(this.myname)
}

var person = {
    myname: 'inside name',
    sayName: sayName,
    other: {
        myname: 'other name',
        sayName: sayName,
    }
}

person.sayName() // 'inside name'
person.other.sayName() // 'other name'

将对象中的函数赋值成变量,这样又变成普通函数,this指向顶层对象。

var newSayName = person.sayName;
newSayName() // 'outside name'

所以,通过上面我们可以看出来, 函数的定义位置不影响其this指向,this指向只和调用函数的对象有关

call、apply、bind改变this指向

通过call、apply、bind可以改变函数this的指向

语法:

fun.call(thisArg, arg1, arg2, ...)
fun.apply(thisArg, [arg1, arg2, ...])

thisArg是fun函数在运行时指定的this的值。但是指定的this值不一定就是该函数执行时真正的this值。如果这个函数处于非严格模式下,指定为null和undefined的this值会自动指向全局对象(windows中就是window对象);指定为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象;

var sayName = function(name1,name2){
    console.log(this, name1, name2) 
}

// Number {1} 'a' 'b'
sayName.call(1, 'a', 'b')

// Window { … } 'a' 'b'
sayName.call(null, 'a', 'b')

// Window { … } 'a' 'b'
sayName.call(undefined, 'a', 'b')

apply和call类似。只是参数不一样。它的参数是数组(或者类数组)。

sayName.apply(1, ['a', 'b'])

严格模式下,指向null和undefined的this值还是指向原来的。

var sayName = function(name1,name2){
    'use strict'
    console.log(this, name1, name2) 
}

sayName.call(null, 'a', 'b')
// null 'a' 'b'

bind和call和apply的调用方式相同,第一个值也是修改this的指向,只不过bind返回一个新的函数。

构造函数调用模式

function Dog(name){
    this.name = name;
    console.log(this)
}

var puppy = new Dog('apple')
// Dog {name: "apple"}

由此可知,new操作符调用时,this指向生成的新对象。

原型链中的调用模式

function Dog(name){
    this.name = name;
}

var puppy = new Dog('apple')
Dog.prototype.bark = function(){
    console.log(this, this.name)
}
puppy.bark()
//Dog {name: "apple"} "apple"

箭头函数调用模式

先看箭头函数和普通函数的重要区别:

  1. 没有自己的this、super、arguments和new.target绑定。
  2. 不能使用new来调用。
  3. 没有原型对象。
  4. 不可以改变this的绑定。
  5. 形参名称不能重复。

箭头函数中没有this绑定,必须通过查找作用域链来决定其值。 如果箭头函数被非箭头函数包含,则this绑定的是最近一层非箭头函数的this,否则this的值则被设置为全局对象。 比如:

var name = 'out'
var people = {
    name: 'xyf',
    sayName: function(){
        var arrowFun = () => {
            console.log(this.name)
        }
        arrowFun()
    },
    arrowSayName: () => {
        console.log(this.name)
    }
}
people.sayName()
people.arrowSayName()

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

查看所有标签

猜你喜欢:

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

C++ Primer 中文版(第 4 版)

C++ Primer 中文版(第 4 版)

Stanley B.Lippman、Josée LaJoie、Barbara E.Moo / 李师贤、蒋爱军、梅晓勇、林瑛 / 人民邮电出版社 / 2006 / 99.00元

本书是久负盛名的C++经典教程,其内容是C++大师Stanley B. Lippman丰富的实践经验和C++标准委员会原负责人Josée Lajoie对C++标准深入理解的完美结合,已经帮助全球无数程序员学会了C++。本版对前一版进行了彻底的修订,内容经过了重新组织,更加入了C++ 先驱Barbara E. Moo在C++教学方面的真知灼见。既显著改善了可读性,又充分体现了C++语言的最新进展和当......一起来看看 《C++ Primer 中文版(第 4 版)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具