《不一样的javascript》系列
- this指向问题
前言
this指向一直以来都是困扰我的问题,看完本书后有一些明悟,记录一下
提示:以下是本篇文章正文内容,下面案例可供参考
一、what is this?
MDN描述:
在绝大多数情况下,函数的调用方式决定了 this 的值(运行时绑定)
当前执行上下文(global、function 或 eval)的一个属性,在非严格模式下,总是指向一个对象,在严格模式下可以是任意值。
执行上下文可以了解为执行环境,可以当成一个对象。这个系列以后写。 那它是指向函数本身吗,还是指向函数作用域呢?还是其他?
二、绑定
1. 绑定时间与位置
绑定时间
函数调用时绑定
绑定位置
- 取决于函数在哪里调用
- this永远不指向函数作用域,
因为函数作用域是一套变量标识符查找规则,也可以看作一个对象, 但是作用域无法通过代码访问,它存在js引擎内部 这个和 [[pototype]]属性一样你是访问不到的
2. 四大绑定规则
2.1 默认绑定
- 独立调用函数或者call,apply绑定null 和undefined
- 分为严格模式和非严格模式
- 非严格模式绑定全局对象
function foo() {
console.log(this.a);
function bar() {
console.log(b);
}
bar()
}
var a = 3;
var b = 4;
foo();
- 严格模式 绑定undefined
function foo() {
'use strict'
console.log(this.a)
}
var a = 3;
foo();
2.2 隐式绑定
- 调用位置有上下文对象,或者这么说:被某个对象包含或者拥有(对象.调用函数)
function foo() {
console.log(this.a)
}
var obj = {
foo: foo,
a: 2
}
var a = 3;
obj.foo();
- 隐式丢失:丢失绑定对象,采用了默认绑定。其实就是暴露了函数使他变成独立执行。
function foo() {
console.log(this.a)
}
var obj = {
foo: foo,
a: 2
}
var a = '233'
var bar = obj.foo
bar();
其实这里obj.foo 指向引用了foo的引用,bar()相当于默认绑定了。
function foo() {
console.log(this.a)
}
function doFoo(fn) {
fn()
}
var obj = {
foo: foo,
a: 2
}
var a = '2333'
doFoo(obj.foo);
2.3 显示绑定
就是通过call apply 函数改变this 指向
function foo(something) {
console.log(this.a, something);
return this.a + something;
}
function bind(fn, obj) {
return function() {
return fn.apply(obj, arguments)
}
}
var obj = {
a: 2
}
var a = 3;
var bar = bind(foo, obj);
var res = bar(3)
console.log(res);
这和原生bind很像了。
2.4. new 绑定
new 构造函数 它会做什么呢
- 创建一个全新对象
- 新对象连接__proto__
- 新对象绑定到函数调用this
- 如果函数没有其他对象,返回新对象
3. 优先级
new>显示绑定>隐式绑定>默认绑定
4 .箭头函数
根据外层作用域来决定this,这里是书的描述(存疑,为什么不是外层调用函数的执行上下文的this) 我的理解是箭头函数绑定在外层函数调用时绑定在外层函数的this,一旦外层函数调用的this不同箭头函数则不同,可以参考下面题二
三、做道题
var myObject = {
foo: 'bar',
func: function() {
var self = this
console.log(this.foo);
console.log(self.foo);
(function() {
console.log(this.foo);
console.log(self.foo);
}())
}
}
var foo = 'window'
myObject.func()
var name = 'window'
function Person(name) {
this.name = name
this.obj = {
name: 'obj',
foo1: function() {
return function() {
console.log(this.name)
}
},
foo2: function() {
return () => {
console.log(this.name)
}
}
}
}
var person1 = new Person('person1')
var person2 = new Person('person2')
person1.obj.foo1()()
person1.obj.foo1.call(person2)()
person1.obj.foo1().call(person2)
person1.obj.foo2()()
person1.obj.foo2.call(person2)()
person1.obj.foo2().call(person2)
|