- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
我们知道浏览器运行环境下在全局作用域下的this是指向window的,但是开发中却很少在全局作用域下去使用this,通常都是在函数中进行使用,而函数使用不同方式进行调用,其this的指向是不一样的。JavaScript中函数在被调用时,会先创建一个函数执行上下文(FEC),而这个上下文中记录着函数的调用栈、活动对象(AO)以及this等等。那么this到底指向什么呢?下面一起来看看this的四个绑定规则。
在进行独立函数调用时,this就会使用默认绑定,而默认绑定的值就是全局的window。独立函数调用可以简单认为函数没有被绑定到某个对象上进行调用。
满足默认绑定的函数调用情况:
function foo() {
console.log(this)
}
foo() // window
function foo1() {
console.log(this) // window
}
function foo2() {
console.log(this) // window
foo1()
}
function foo3() {
console.log(this) // window
foo2()
}
foo3()
function foo() {
return function() {
console.log(this)
}
}
const fn = foo()
fn() // window
将对象中的方法赋值给别人,别人再进行调用,虽然是对象中的方法再次赋值,最后被赋值的对象都是进行独立函数调用的;
obj中的bar方法作为参数传递到foo函数中,然后进行调用(最后被传递的参数进行了独立调用)
function foo(func) {
func()
}
const obj = {
bar: function() {
console.log(this)
}
}
foo(obj.bar) // window
const obj = {
bar: function() {
console.log(this)
}
}
const fn = obj.bar
fn() // window
隐式绑定是开发中比较常见的,通过某个对象对函数进行调用,也就是说函数的调用是通过对象发起的,常见为对象中方法的调用(这个对象会被js引擎绑定到函数中的this里面)。
满足隐式绑定的函数调用情况:
const obj = {
foo: function() {
console.log(this)
}
}
obj.foo() // obj对象
function bar() {
console.log(this)
}
const obj = {
foo: bar
}
obj.foo() // obj对象
const obj1 = {
name: 'obj1',
obj2: {
name: 'obj2',
foo: function() {
console.log(this)
}
}
}
obj1.obj2.foo() // obj2对象
如果我们不希望使用隐式绑定的对象,而想在调用函数时给this绑定上自己想绑定的东西,那么这样的行为就称为显示绑定,显示绑定主要借助于三个方法,分别为call、apply和bind。
JS中所有的函数都有call和apply方法属性(主要是其原型链上实现了这两个方法),可以说这两个函数就是给this准备的。简单介绍一下这两个函数的区别:在进行函数调用时,都可以使用call和apply进行调用,其传入的第一个参数都是一样的,也就是我们希望给this绑定的值,后面的参数apply对应为包含多个参数的数组,call对应为参数列表。
function foo() {
console.log(this)
}
const obj = {
name: 'curry',
age: 30
}
foo() // window
foo.call(obj) // obj对象
foo.apply(obj) // obj对象
function sum(x, y) {
console.log(this, x + y)
}
const obj = {
name: 'curry',
age: 30
}
sum(10, 20) // window 30
sum.call(obj, 10, 20) // obj对象 30
sum.apply(obj, [10, 20]) // obj对象 30
function foo() {
console.log(this)
}
// 1.绑定字符串
foo.call('aaa')
foo.apply('bbb')
// 2.绑定字符串
foo.call(111)
foo.apply(222)
// 3.绑定数组
foo.call([1, 2, 3])
foo.apply(['a', 'b', 'c'])
call和apply可以帮助我们调用函数明确this的绑定对象,而bind与这两种的用法不太一样。如果希望一个函数的this可以一直绑定到某个对象上,那么bind就可以派出用场了。
function foo() {
console.log(this)
}
const obj = {
name: 'curry',
age: 30
}
const newFoo = foo.bind(obj)
newFoo() // obj对象
function foo() {
console.log(this)
}
const obj1 = {
name: 'curry',
age: 30
}
const obj2 = {
name: 'kobe',
age: 24
}
const newFoo = foo.bind(obj1)
newFoo() // obj1对象
newFoo.call(obj2) // obj1对象
newFoo.apply(obj2) // obj1对象
const obj3 = {
bar: newFoo
}
obj3.bar() // obj1对象
JavaScript中的函数不仅可以通过上面的方法进行调用,还可以使用new关键字来调用函数,当使用new来调用的函数,一般称为构造函数(ES6中的类),以这样的方式来调用的函数this所绑定的值,就叫做new绑定。
构造函数一般用于创建对象,通过new调用构造函数可以返回一个实例对象,而this绑定就是这个实例对象。那么使用new调用时,函数内部会进行哪些操作呢?如下:
function Student(sno, name, age) {
this.sno = sno
this.name = name
this.age = age
console.log('this: ', this)
}
const stu1 = new Student(1, 'curry', 30) // this: {sno: 1, name: "curry", age: 30}
console.log(stu1) // Student {sno: 1, name: "curry", age: 30}
const stu2 = new Student(2, 'kobe', 24) // this: {sno: 2, name: "kobe", age: 24}
console.log(stu2) // Student {sno: 2, name: "kobe", age: 24}
console.log(stu1.__proto__ === Student.prototype) // true
console.log(stu2.__proto__ === Student.prototype) // true
setTimeout(function() {
console.log(this) // window
}, 1000)
// ------相当于------
function mySetTimeout(callback, delay) {
callback() // 独立函数调用
}
const boxDiv = document.querySelector('.box')
boxDiv.onclick = function() {
console.log(this) // boxDiv(DOM对象)
}
boxDiv.addEventListener('click', function() {
console.log(this) // boxDiv(DOM对象)
})
const arr = [1, 2, 3, 4, 5]
const obj = {
name: 'curry',
age: 30
}
arr.forEach(function() {
console.log(this) // obj对象
}, obj)
arr.map(function() {
console.log(this) // obj对象
}, obj)
arr.filter(function() {
console.log(this) // obj对象
}, obj)
上面提到了this的四种绑定规则,如果在函数调用时,使用到了多种绑定规则,最终函数的this指向什么呢?那么这里就涉及到this绑定的优先级,优先级高的规则决定this的最终绑定。
this四种绑定规则优先级如下:
const obj1 = {
name: 'obj1',
foo: function() {
console.log(this)
}
}
const obj2 = {
name: 'obj2'
}
obj1.foo.call(obj2) // obj2对象
obj1.foo.apply(obj2) // obj2对象
const newFoo = obj1.foo.bind(obj2)
newFoo() // obj2对象
function foo() {
console.log(this)
}
const obj1 = {
name: 'curry',
age: 30
}
const obj2 = {
name: 'kobe',
age: 24
}
const newFoo = foo.bind(obj1)
newFoo() // obj1对象
newFoo.call(obj2) // obj1对象
newFoo.apply(obj2) // obj1对象
// 1.new绑定高于隐式绑定
const obj1 = {
foo: function() {
console.log(this)
}
}
const f = new obj1.foo() // foo函数对象
// 2.new绑定高于显示绑定
function foo(name) {
console.log(this)
}
const obj2 = {
name: 'obj2'
}
const newFoo = foo.bind(obj2)
const nf = new newFoo(123) // foo函数对象
总结:
在特殊情况下,this的绑定不一定满足上面的绑定规则,主要有以下特殊情况:
function foo() {
console.log(this)
}
foo.call(null) // window
foo.call(undefined) // window
foo.apply(null) // window
foo.apply(undefined) // window
const newFoo1 = foo.bind(null)
const newFoo2 = foo.bind(undefined)
newFoo1() // window
newFoo2() // window
const obj1 = {
name: 'obj1',
foo: function() {
console.log(this)
}
}
const obj2 = {
name: 'obj2'
}
// 被认为是独立函数调用
;(obj2.bar = obj1.foo)() // window
ES6中的箭头函数:箭头函数不会使用上面的四种绑定规则,也就是说不绑定this,箭头函数的this是根据它外层作用域中的this绑定来决定的;
数组内置方法中回调使用箭头函数:
const names = ['curry', 'kobe', 'klay']
const obj = {
name: 'obj'
}
names.map(() => {
console.log(this) // window
}, obj)
const obj1 = {
name: 'obj1',
obj2: {
name: 'obj2',
foo: () => {
console.log(this)
}
}
}
obj1.obj2.foo() // window
function foo() {
return () => {
console.log(this)
}
}
const obj = {
name: 'curry',
age: 30
}
const bar = foo.call()
bar() // obj对象
以上提到的内容都是在浏览器环境中进行测试的,在浏览器环境下的this是指向全局window的,那么在node环境中全局this指向什么呢?
为什么全局this打印为一个空对象?
当我们js文件被node执行时,该js文件会被视为一个模块;
node加载编译这个模块,将模块中的所有代码放入到一个函数中;
然后会执行这个函数,在执行这个函数时会通过apply绑定一个this,而绑定的this就为{}
;
那为什么node中还是可以使用想window中的全局方法呢?像setTimeout、setInterval等。
因为node环境中也是存在全局对象的,通过打印globalThis
就可以进行查看;
我有一个 html 格式的表单: 我需要得到 JavaScript在value input 字段执行,但只能通过表单的 submit .原因是页面是一个模板所以我不控制它(不能有
我管理的论坛是托管软件,因此我无法访问源代码,我只能向页面添加 JavaScript 来实现我需要完成的任务。 我正在尝试用超链接替换所有页面上某些文本关键字的第一个实例。我还根据国家/地区代码对这些
我正在使用 JS 打开新页面并将 HTML 代码写入其中,但是当我尝试使用 document.write() 在新页面中编写 JS 时功能不起作用。显然,一旦看到 ,主 JS 就会关闭。用于即将打开的
提问不是为了解决问题,提问是为了更好地理解系统 专家!我知道每当你将 javascript 代码输入 javascript 引擎时,它会立即由 javascript 引擎执行。由于没有看过Engi
我在一个文件夹中有两个 javascript 文件。我想将一个变量的 javascript 文件传递到另一个。我应该使用什么程序? 最佳答案 window.postMessage用于跨文档消息。使
我有一个练习,我需要输入两个输入并检查它们是否都等于一个。 如果是 console.log 正则 console.log false 我试过这样的事情: function isPositive(fir
我正在做一个Web应用程序,计划允许其他网站(客户端)在其页面上嵌入以下javascript: 我的网络应用程序位于 http://example.org 。 我不能假设客户端网站的页面有 JQue
目前我正在使用三个外部 JS 文件。 我喜欢将所有三个 JS 文件合而为一。 尽一切可能。我创建 aio.js 并在 aio.js 中 src="https://code.jquery.com/
我有例如像这样的数组: var myArray = []; var item1 = { start: '08:00', end: '09:30' } var item2 = {
所以我正在制作一个 Chrome 扩展,它使用我制作的一些 TamperMonkey 脚本。我想要一个“主”javascript 文件,您可以在其中包含并执行其他脚本。我很擅长使用以下行将其他 jav
我有 A、B html 和 A、B javascript 文件。 并且,如何将 A JavaScript 中使用的全局变量直接移动到 B JavaScript 中? 示例 JavaScript) va
我需要将以下整个代码放入名为 activate.js 的 JavaScript 中。你能告诉我怎么做吗? var int = new int({ seconds: 30, mark
我已经为我的 .net Web 应用程序创建了母版页 EXAMPLE1.Master。他们的 I 将值存储在 JavaScript 变量中。我想在另一个 JS 文件中检索该变量。 示例1.大师:-
是否有任何库可以用来转换这样的代码: function () { var a = 1; } 像这样的代码: function () { var a = 1; } 在我的浏览器中。因为我在 Gi
我收到语法缺失 ) 错误 $(document).ready(function changeText() { var p = document.getElementById('bidp
我正在制作进度条。它有一个标签。我想调整某个脚本完成的标签。在找到可能的解决方案的一些答案后,我想出了以下脚本。第一个启动并按预期工作。然而,第二个却没有。它出什么问题了?代码如下: HTML:
这里有一个很简单的问题,我简单的头脑无法回答:为什么我在外部库中加载时,下面的匿名和onload函数没有运行?我错过了一些非常非常基本的东西。 Library.js 只有一行:console.log(
我知道 javascript 是一种客户端语言,但如果实际代码中嵌入的 javascript 代码以某种方式与在控制台上运行的代码不同,我会尝试找到答案。让我用一个例子来解释它: 我想创建一个像 Mi
我如何将这个内联 javascript 更改为 Unobtrusive JavaScript? 谢谢! 感谢您的回答,但它不起作用。我的代码是: PHP js文件 document.getElem
我正在寻找将简单的 JavaScript 对象“转储”到动态生成的 JavaScript 源代码中的最优雅的方法。 目的:假设我们有 node.js 服务器生成 HTML。我们在服务器端有一个对象x。
我是一名优秀的程序员,十分优秀!