网页的本质就是超级文本标记语言,通过结合使用其他的Web技术(如:脚本语言、公共网关接口、组件等),可以创造出功能强大的网页。因而,超级文本标记语言是万维网(Web)编程的基础,也就是说万维网是建立在超文本基础之上的。超级文本标记语言之所以称为超文本标记语言,是因为文本中包含了所谓“超级链接”点。
本章给大家带来Javascript中什么是this?this的4种绑定方式(介绍)。有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所帮助。
什么是this?
当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this就是记录的其中一个属性,会在函数执行的过程中用到。
this的4种绑定方式
默认绑定
function foo() {
console.log( this.a );
}
var a = 2;
foo(); // 2
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
obj.foo(); // 2这段代码this绑定到了obj对象,当函数引用有上下文对象(context)时,隐式绑定规则会把this绑定到这个上下文对象。
隐式丢失问题
// 例子1111
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
var bar = obj.foo; // 函数别名!
?
var a = "oops, global"; // a是全局对象的属性”
bar(); // "oops, global"
//2222
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
var a = "oops, global"; // a是全局对象的属性
setTimeout( obj.foo, 100 ); // "oops, global例子1111虽然bar是obj.foo的一个引用,但是实际上,它引用的是foo函数本身,因此此时的bar()其实是一个不带任何修饰的函数调用,因此应用了默认绑定。例子222在setTimeout函数中丢失了this绑定,道理是一样的,我们可以把参数传递看成一种隐式赋值。
显式绑定
在分析隐式绑定时,我们必须在一个对象内部包含一个指向函数的属性,并通过这个属性间接引用函数,从而把this间接(隐式)绑定到这个对象上。
那么如果我们不想在对象内部包含函数引用,而想在某个对象上强制调用函数,该怎么做呢?
学过js的估计对 call,apply和bind都不陌生,js提供的这些原生方法就给我们提供了显式绑定this的途径。
function foo() {
console.log( this.a );
}var obj = {
a:2};
foo.call( obj ); // 2通过foo.call(..),我们可以在调用foo时强制把它的this绑定到obj上。
如果你传入了一个原始值(字符串类型、布尔类型或者数字类型)来当作this的绑定对象,这个原始值会被转换成它的对象形式(也就是new String(..)、new Boolean(..)或者new Number(..))。这通常被称为“装箱”。
“从this绑定的角度来说,call(..)和apply(..)是一样的,它们的区别体现在其他的参数上,但是现在我们不用考虑这些。”
硬绑定-bind的实现
我们已经知道了this绑定的4种方式,但是使用call和apply我们还是不能解决隐式丢失的问题,思考以下例子:
function foo() {
console.log( this.a );
}
var obj = {
a:2
};
var bar = function() {
foo.call( obj );
};
bar(); // 2
setTimeout( bar, 100 ); // 2
bar.call(windows) //无法再修改this通过call我们在函数bar内强制指定了foo的this,之后不论如何调用bar,它总会在obj上手动调用foo,这种绑定是一种显示强制绑定,因此称为硬绑定。这就是bind的产生来由(因为硬绑定比较常用,es5中新增了bind方法),通过硬绑定制定this,上面代码现在就变成了
...略var bar = foo.bind(obj)
bar(); // 2setTimeout( bar, 100 ); // 2绑定规则优先级和es6的this新特性
如果要判断一个运行中函数的this绑定,就需要找到这个函数的直接调用位置。找到之后就可以顺序应用下面这四条规则来判断this的绑定对象。
由new调用?绑定到新创建的对象。
由call或者apply(或者bind)调用?绑定到指定的对象。
由上下文对象调用?绑定到那个上下文对象。
默认:在严格模式下绑定到undefined,否则绑定到全局对象。
几个小例子看懂this
unction showThis () { console.log(this)
}function showStrictThis () { 'use strict'
console.log(this)
}
showThis() // windowshowStrictThis() // undefined优先级最小的this对象,默认绑定。
思考下面的例子:
var person = { name: '11',
showThis () { return this
}
}
person.showThis() === person //truevar person2 = { name: '22',
showThis () { return person.showThis()
}
}var person3 = { name: '33',
showThis () { var retrunThis = person.showThis return retrunThis()
}
}
person.showThis() //personperson2.showThis() //?person3.showThis() //?我们首先要找到调用位置,在2里是这句return person.showThis(),隐式绑定了一个person对象,所以输出person ,3 是return retrunThis() ,this默认绑定到全局,返回window.
function showThis () {
return this
}
var person = { name: 'person' }
showThis() // window
showThis.call(p1) // person
showThis.apply(p1) // person通过显式绑定指定了context object。
function showThis () {
return this
}
var person = { name: 'person' }
var personBind = showThis.bind(person)
personBind() //person
var person2 = { name: 'person2' }
personBind.call(person2) //personbind方法强绑定了this,已经无法再通过显式绑定切换this。
function showThis () {
return this
}
var person = { name: 'person' }
var person2 = { name: 'person2' }
var personBind = showThis.bind(person)
personBind() //person
new personBind() //showThisnew优先级高于bind,所以可以覆盖this。
function foo() {
setTimeout(() => {
// 这里的this在词法上继承自foo()
console.log( this.a );
},100);
}var obj = {
a:2};
foo.call( obj ); // 2箭头函数并不是使用function关键字定义的,而是使用被称为“胖箭头”的操作符=>定义的。箭头函数不使用this的四种标准规则,而是根据外层(函数或者全局)作用域来决定this。箭头函数的绑定无法被修改,包括new。 关于箭头函数网上有很多详细全面的讲解。这里不再展开。
以上就是Javascript中什么是this?this的4种绑定方式(介绍)的详细内容,更多请关注php中文网其它相关文章!
网站建设是一个广义的术语,涵盖了许多不同的技能和学科中所使用的生产和维护的网站。
关键词:Javascript中啥是this?this的4种绑定方式(介绍)