网站建设之JavaScript中的“ this”如何工作

该this关键字可以是非常混乱。本教程将帮助您了解其工作原理。您将了解如何this在不同的上下文和环境下工作。这些上下文包括全局对象,函数,对象和类的方法和事件。您还将了解globalThisES2020中添加的新功能。 WP网站建设 介绍 该this是存在不只是在JavaScript中,而且在其他编程语言的 WP网站建设

this关键字可以是非常混乱。本教程将帮助您了解其工作原理。您将了解如何this在不同的上下文和环境下工作。这些上下文包括全局对象,函数,对象和类的方法和事件。您还将了解globalThisES2020中添加的新功能。

WordPress网站建设

WordPress网站建设

介绍

this是存在不只是在JavaScript中,而且在其他编程语言的特殊关键字。JavaScript的this不同之处在于在不同模式下的行为不同。在JavaScript中,有两种模式:严格和非严格。非严格模式是普通模式。有时也称为“马虎”模式。

什么this是指总是依赖于它定义的执行上下文。执行上下文是当前环境或范围,在其中声明正在执行的代码行。在运行时,JavaScript会维护所有执行上下文的堆栈。

该堆栈顶部的执行上下文是正在执行的上下文。当执行上下文更改时,更改的值也将this更改。让我们看一下this在不同上下文中指的是什么。

请注意严格模式

严格模式旨在帮助您使JavaScript代码更简洁。它通过建立一些特殊规则来做到这一点。例如,必须先明确声明所有变量,然后才能为其分配值。您的函数必须在全局范围内声明。在函数内部,禁止对变量和函数参数使用相同的名称。

也禁止删除不可变的属性和不合格的标识符。所有这些以及许多其他事情都会引发错误。这是严格和非严格模式之间的另一个区别。在非严格模式下,许多错误是静默的。严格来说,它们不是。违反严格模式规则的所有内容都将引发错误。

除了这些规则外,严格模式还改变了this行为方式。为了更好的说明,我们将讨论如何在每个特定的上下文中。关于严格模式的最后一件事。如果要切换到严格模式'use strict';,请在代码顶部添加语句。

注意:您可以为所有代码或仅为特定功能打开严格模式。区别在于您在哪里使用该'use strict';语句。在全局范围的顶部使用它,它将应用于随后的所有代码。在函数顶部使用它,它将仅应用于该函数内部的代码。

全球范围内的“这个”

在JavaScript中,当this在全局上下文中定义时this,默认情况下指的是Global对象。对于浏览器,此全局对象是window对象。此全局对象是顶级范围。对于this全局上下文,严格模式没有任何区别。无论您处于严格模式还是非严格模式,this行为都将相同。

// global context and this in non-strict mode
console.log(this === window)
// true


// global context and this in strict mode
'use strict'

console.log(this === window)
// true

“ this”,全局上下文和Node.js

对于Node.js,没有window对象。在Node.js中,全局对象是一个特殊的对象,称为global。这意味着在全球范围内this将引用this global。好吧,差不多。这仅在Node.js内部是正确的。要对此进行测试,请首先启动您喜欢的控制台并输入node

此命令将打开Node.js环境,因此您可以直接使用它。之后,您可以测试this全局上下文中的引用。如果您的计算机上没有Node.js,则可以从Node.js 网站获取。

// In node environment
> console.log(this === global)
// true

> console.log(this)
// Object [global] {
//   global: [Circular],
//   clearInterval: [Function: clearInterval],
//   clearTimeout: [Function: clearTimeout],
//   setInterval: [Function: setInterval],
//   setTimeout: [Function: setTimeout] { [Symbol(util.promisify.custom)]: [Function] },
//   queueMicrotask: [Function: queueMicrotask],
//   clearImmediate: [Function: clearImmediate],
//   setImmediate: [Function: setImmediate] {
//     [Symbol(util.promisify.custom)]: [Function]
//   }
// }

如果从JavaScript文件运行代码,结果将有所不同。当您在Node.js中使用JavaScript文件时,本地代码仅限于该文件。那里的一切都不是全球性的,而是本地性的。结果,this不是指global,而是指module.exports

// In node environment, in JavaScript file
console.log(this === global)
// false

console.log(this === module.exports)
// true

功能和“ this”

对于JavaScript顶级功能,模式很重要。顶层是指在全局范围内声明的函数,而不是在对象或类内部声明的函数。如果您在非严格模式下工作,thiswindow在浏览器的情况下将引用全局对象。

// Function in a non-strict mode
function testThis() {
  console.log(this === window)
}

testThis()
// true

让我们use strict在函数顶部添加语句以打开严格模式。现在,结果将有所不同。this将不再引用全局对象,例如window。当您尝试获取thisJavaScript 的值时将返回undefined。这是因为this现在未设置的值。

// Function in a non-strict mode
function testThis() {
  'use strict' // switch on strict mode for this function
  console.log(this === window)

  console.log(this)
}

testThis()
// false
// undefined

函数,this和call()和apply()

有一种方法可以设置this您在调用函数时的值,而不必设置它undefined。为此,您可以使用call()apply()bind()方法。这称为“显式函数绑定”。当您使用这些方法之一时,您将this作为参数传递值。前两个call()apply()几乎相同。

区别在于apply()接受参数列表与call()接受参数数组相同。apply()还允许您使用数组文字。

// Set value of this with apply()
function testThisWithApply() {
  'use strict'

  console.log('Value of this: ', this)
}

// set value of "this" to one
testThis.apply('one')
// 'Value of this: one'


// Set value of this with call()
function testThisWithCall() {
  'use strict'

  console.log('Value of this: ', this)
}

// set value of "this" to one
testThis.call('one')
// 'Value of this: one'

函数,this和bind()

bind()方法是不同的。当您要调用或调用一个函数时,不要使用此方法。而是使用该bind()方法来创建新的“绑定”函数。之后,您将调用新的“绑定”函数,而不是原始函数。现在,价值this就是您想要的价值。

// Set value of this with bind()
function testThisWithBind() {
  'use strict'

  console.log('Value of this: ', this)
}

// Create bound function and set value of "this" to "one"
const newTestThisWithBind = testThisWithBind.bind('one')

// Invoke new "bound" function "newTestThisWithBind"
newTestThisWithBind()
// 'Value of this:  one'


// Or, with reassigning the original function
function testThisWithBind() {
  'use strict'

  console.log('Value of this: ', this)
}

// Create bound function and set value of "this" to "reassigned!"
testThisWithBind = testThisWithBind.bind('reassigned!')

// Test: Invoke now "bound" function "testThisWithBind"
testThisWithBind()
// 'Value of this:  reassigned!'

关于bind()要记住的方法,有一件重要的事情。它只能工作一次。您不能bind()多次更改this“ bound”函数的值。但是,您可以将其与原始函数一起使用多次,以创建新的“绑定”函数。

// Doesn't work: Try to re-set this of bound function
function testThisWithBind() {
  'use strict'

  console.log('Value of this: ', this)
}

// Create bound function
// and set value of "this" to "one"
const newTestThisWithBind = testThisWithBind.bind('one')


// Test: Invoke new "bound" function "newTestThisWithBind"
newTestThisWithBind()
// The value of "this" is not correct
// 'Value of this:  one'


// Create another bound function
// using the bound function
// and try to change value of "this"
const newerTestThisWithBind = newTestThisWithBind.bind('two')

// Test: Invoke newer "bound" function "newerTestThisWithBind"
newerTestThisWithBind()
// The value of "this" is correct
// 'Value of this: one'


// Works: Create another bound function from the original
const brandNewThisWithBind = testThisWithBind.bind('two')

// Test: Invoke newer "bound" function "brandNewThisWithBind"
brandNewThisWithBind()
// The value of "this" is correct
// 'Value of this: two'



// Test: Invoke newer "bound" function "newerTestThisWithBind"
// The value of "this" is the same
newerTestThisWithBind()
// 'Value of this: one'

注意:这适用于熟悉React和类组件的人员。你可能会认识到喜欢的东西this.myFunc = this.myFunc.bind(this)constructor。这是因为它需要一个函数并创建一个绑定函数并返回它,并且基本上覆盖了原始函数。

在这种情况下,thishere 的值是this,即类组件本身。this在这种情况下,更改绑定的另一种方法是使用箭头功能

箭头功能和“ this”

ES6中引入的箭头功能与常规功能不同。箭头函数没有自己的this。它们始终使用与this其父级相同的值来声明它们的执行上下文。箭头函数的另一重要事项是您不能this显式设置其值。

当您尝试使用call()apply()bind()用箭头功能什么都不会发生。箭头函数将忽略这些方法。

// Arrow function inside an object
const user = {
  username: 'franky',
  email: 'franky@frankyrocks.io',
  // Get data with arrow function
  getUserWithArrowFunction: () => {
    // This refers to global object, window
    // So, this.username is like window.username
    return `${this.username}, ${this.email}.`
  },
  // Get data with normal function
  getUserWithNormalFunction: function() {
    // This refers to myObj
    // So, this.username is like myObj.username
    return `${this.username}, ${this.email}.`
  }
}

// Test the arrow function
user.getUserWithArrowFunction()
// TypeError: Cannot read property 'title' of undefined

// Test the normal function
user.getUserWithNormalFunction()
// 'franky, franky@frankyrocks.io.'


///
// Arrow functions and binding
let arrowFunctionWithBind = () => {
  'use strict'

  console.log('Value of this: ', this)
}

// Try to create bound function
// and set value of "this" to "arrow!"
arrowFunctionWithBind = arrowFunctionWithBind.bind('arrow!')


// Test: Invoke new "bound" function "arrowFunctionWithBind"
arrowFunctionWithBind()
// 'Value of this: undefined

由于this箭头函数的工作方式,箭头函数是回调的理想选择。请记住,箭头函数始终this从其封闭的执行上下文继承。使用箭头功能,可以this在回调中进行访问而不必担心是什么this

// Functions as callbacks
// Using normal function as a callback
const counter = {
  count: 0,
  addCount() {
    // Use normal function as a callback in setInterval
    setInterval(function() {
      // 'this' here is Global object
      // So, ++this.count is like ++window.count
      console.log(++this.count)
    }, 1000)
  }
}

// Invoke addCount() method
counter.addCount()
// NaN
// NaN
// NaN
// NaN
// NaN
// ...


// Using arrow function as a callback
const counter = {
  count: 0,
  addCount() {
    // Use arrow function as a callback in setInterval
    setInterval(() => {
      // 'this' here is the "counter" object
      // So, ++this.count is like ++counter.count
      console.log(++this.count)
    }, 1000)
  }
}

// Invoke addCount() method
counter.addCount()
// 1
// 2
// 3
// 4
// 5
// ...


///
// What "this" is
// Using normal function as a callback
const counter = {
  logThis() {
    // Use normal function as a callback in setInterval
    setInterval(function() {
      console.log(this)
    }, 1000)
  }
}

// Invoke logThis() method
counter.logThis()
// Window
// Window
// Window
// ...


// What "this" is
// Using arrow function as a callback
const counter = {
  logThis() {
    // Use normal function as a callback in setInterval
    setInterval(() => {
      console.log(this)
    }, 1000)
  }
}

// Invoke logThis() method
counter.logThis()
// { logThis: [Function: logThis] }
// { logThis: [Function: logThis] }
// { logThis: [Function: logThis] }
// ...

对象方法和“ this”

假设您this在对象内部的函数内部使用。在这种情况下,的值this将是在其中声明该方法的对象。这与JavaScript模式无关。

// Create object
const animal = {
  name: 'Cat',
  class: 'Mammalia',
  order: 'Carnivora',
  genus: 'Felis',
  logAnimal: function() {
    return this;
  }
}

// Call logAnimal() method
animal.logAnimal()
// {
//   name: 'Cat',
//   class: 'Mammalia',
//   order: 'Carnivora',
//   genus: 'Felis',
//   logAnimal: [Function: logAnimal]
// }

声明函数在对象内部还是外部并附加它都没有关系。

// Create empty object
const thing = {}

// Add property to "thing" object
thing.itemName = 'Box'

// Add method to "thing" object
thing.getItemName = function() {
  return this.itemName
}

thing.returnThis = function() {
  return this
}

// Invoke getItemName() method
thing.getItemName()
// 'Box'

thing.returnThis()
// {
//   itemName: 'Box',
//   getItemName: [Function],
//   returnThis: [Function]
// }

函数构造函数和“ this”

this函数构造函数中使用时,其值将始终引用该构造函数创建的新对象。

// Create function constructor
function Phone(model, brand) {
  this.model = model
  this.brand = brand
  this.getModelAndBrand = function() {
    // "this" refers to new Phone object
    // created using "new" keyword
    return `Model: ${this.model}, brand: ${this.brand}`
  }
  this.returnThis = function() {
    return this
  }
}

// Create new Phone object using "new" keyword
const iPhoneX = new Phone('iPhone X', 'Apple')
// Here, "this" refers to "iPhoneX"

iPhoneX.getModelAndBrand()
// 'Model: iPhone X, brand: Apple'

iPhoneX.returnThis()
// Phone {
//   model: 'iPhone X',
//   brand: 'Apple',
//   getModelAndBrand: [Function],
//   returnThis: [Function]
// }

类方法和“ this”

this在类方法中使用时,它将引用用该类创建的实例。

// Create new class with two properties
// add two methods
class Brain {
  constructor(numOfHemispheres, iq) {
    this.numOfHemispheres = numOfHemispheres
    this.iq = iq
  }

  getIQ() {
    // This refers to instance of Brain class
    return this.iq
  }

  learn() {
    // This refers to instance of Brain class
    this.iq += 1
  }

  watchTv() {
    // This refers to instance of Brain class
    this.iq -= 1
  }

  returnThis() {
    return this
  }
}

// Create instance of Brain class
// with 2 hemispheres and IQ of 180
const smartBrain = new Brain(2, 180)

// Log the IQ of smartBrain
smartBrain.getIQ()
// 180

// Learn something
smartBrain.learn()

// Log the IQ of smartBrain again
smartBrain.getIQ()
// 181

smartBrain.watchTv()

// Log the IQ of smartBrain again
smartBrain.getIQ()
// 180

smartBrain.returnThis()
// Brain { numOfHemispheres: 2, iq: 180 }

事件和“此”

当您使用this内部事件处理程序时,它将引用您将事件侦听器附加到的元素。

创建一个简单的button元素。

<!-- Create button -->
<button class="btn">Click</button>

附加eventListenerbutton元素。

// Create event handler function
handleButtonClick function() {
  console.log(this)
}

// Find the button in the DOM,
// attach event listener to it
// and pass the handler function as an argument
document.querySelector('.btn').addEventListener('click', handleButtonClick)

现在单击按钮时,您将看到[object HTMLButtonElement]和很多数据。这是按钮元素及其所有属性和方法。

事件,“ this”和箭头功能

如果将箭头函数用作事件处理程序的回调,则会得到不同的结果。这次,您将不会获得[object HTMLButtonElement],及其属性和方法。相反,您将获得[object Window]全局window对象。因此,如果要用于this访问触发事件的元素,请使用常规功能。

如果无论出于何种原因仍要使用箭头功能,则有一种方法。将event作为参数添加到箭头函数。然后,里面那个箭头功能,用途event.targetevent.currentTarget来访问该元素。如果是按钮,您将得到[object HTMLButtonElement]

// Create handler function, now arrow function
// and specify parameter for event
const handleButtonClick = (event) => {
  // Access the value passed as event, not "this"
  console.log(event)
}


// Find the button in the DOM,
// attach event listener to it
// and pass the handler function as an argument
document.querySelector('.btn').addEventListener('click', handleButtonClick)

全球本

globalThis是ES2020中添加的功能之一。此功能旨在与全球合作this。也就是说,用windowselfthisframe在浏览器和对象globalthis在Node.js的 如果使用跨平台JavaScript,则不再需要担心使用正确的对象。

相反,您可以使用新添加的globalThis。使用globalThis,无论平台如何,您都将始终自动选择正确的全局对象。也就是说,globalThis不应该被滥用。您仍应将尽可能多的代码保留在全局范围,函数和代码块之内。

globalThis应主要用于东西,如polyfills和垫片。globalThis还可用于功能检测,以检测特定浏览器或环境中支持哪些JavaScript功能。

// In the browser
globalThis === window
// true

const obj = {
  name: 'foo',
  getThis: function() {
    return this
  },
  getGlobalThis = function() {
    return globalThis
  }
}

obj.getThis()
// {name: "foo", getThis: ƒ}

obj.getGlobalThis()
// Window { ... }


// In Node.js
globalThis === global
// true

结论:JavaScript中的“ this”如何工作

您刚刚到达了本教程的结尾。我希望你喜欢它。我也希望它能帮助您了解this关键字的工作原理和使用方法。该this关键字可以非常混乱,可能需要一些时间去了解它。但是,这是值得的。了解了它之后,您还将更好地了解JavaScript本身。

原创文章,作者:网站建设,如若转载,请注明出处:https://www.davidwu.net/archives/20836

WordPress安全防护插件
服务项目 服务内容 收费标准(元)
开发定制 WordPress主题/插件开发定制 (以最终需求为准)
主题/插件汉化 汉化团队WordPress主题/插件,翻译率95% (以标的主题/插件的句子数量为准)
服务器环境配置 基于您现有服务器,搭建配置网站运行环境,结合我们多年来实战经验,可完美支持WordPress等PHP程序运行,并配置伪静态规则、优化目录权限等问题。服务器我们强烈推荐使用Linux系统。 100元/次
网站托管 若贵站目前尚无技术人员,无法完成服务器环境配置,可选择我们的网站托管服务,直接交付正常运行的WordPress站点,并且无需担心服务器的后续维护工作,一切都由我们来帮您完成。 标配套餐:1000元/年/站点 高配套餐:联系客服获取
网站加速优化 从服务器后端配置优化到WordPress数据库缓存、前端页面缓存、JS和CSS压缩合并,全方位优化网站加载速度,实现秒开。(此服务仅针对(云)服务器/VPS) 500元/次(仅站内优化200元/次)
主题配置 本站所有主题均支持,可快速实现,若有任何问题可以咨询客服解决,若您希望我们提供配置服务,可选购此服务。 英文主题安装 60元/次 汉化主题安装 30元/次
HTTPS配置 HTTPS已经不断普及,并且有着更高的安全性以及SEO上的优待。该服务收取的为服务费,SSL证书产生的费用请自行承担。 100元/次
网站搬家 迁移网站所有文件和数据库信息、网站相关配置的调整、以及迁移中的疑难问题故障排除。 标准收费:500元/次 若网站数据量大,需协商
网站运维 提供整站的运维服务,保证网站正常运行。包含:网站故障定位及排除、网站数据备份和恢复、网站攻击及木马等问题的处理等 标准收费:2000元/年 IP 5000以上需协商

发表评论

电子邮件地址不会被公开。 必填项已用*标注

51建站客服微信二维码
点击这里购买