js基础(六) this
Robin 7/20/2017 javaScript面试
# 知识点一 this
# 原理
- 我们在
js
中主要研究的都是函数中的this
js
中的this
代表的是当前行为执行的主体,js
中的context
代表的是当前行为执行的环境(区域)this
是谁和函数在哪定义的和在哪执行的都没有任何的关系- 如何区分
this
:
# 使用场景
# 场景一 普通函数的调用
核心:普通函数的调用,this指向的是window,例如
function fn() {
console.log(this)
}
fn() // this ---> window
1
2
3
4
5
2
3
4
5
# 场景二 对象方法的调用
核心:对象方法的调用,this指的是该对象,且是最近的对象
- 函数执行,首先看函数名前面是否有
.
,有的话.
前面是谁this
就是谁;没有的话this
就是window
,例如
function fn() {
console.log(this)
}
var obj = {fn: fn}
fn() // this ---> window
obj.fn() // this ---> obj
function sum() {
fn() // this ---> window
}
sum()
var o = {
sum: function() {
console.log(this) // this ---> o
fn() // this ---> window
}
}
o.sum()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- 给元素的某个事件绑定方法,当事件触发的时候,执行对应的方法,方法中的
this
是当前的元素
function fn() {
console.log(this)
}
document.getElementById('div1').onclick = fn // this ---> #div1
document.getElementById('div1').onclick = function() {
console.log(this) // this ---> #div1
fn() // this ---> window
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 场景三 构造函数的调用
核心:构造函数的调用,this指的是实例化的新对象
在构造函数当中,类中(函数体中)出现的 this.xxx
中的 this
是当前类的一个实例
构造函数的公/私有方法中 this
查找步骤:
- 看方法执行的时候,
.
前面是谁,this
就是谁 - 把函数体中的
this
替换成分析的结果 - 按照原型链的查找模式找到对应的值即可
function Fn() {
this.x = 100;
this.y = 200;
this.getX = function() {
console.log(`${this.x}`)
}
}
Fn.prototype.getX = function() {
console.log(`${this.x}`)
}
Fn.prototype.getY = function() {
console.log(`${this.y}`)
}
Fn.prototype.setX = function(n) {
this.x = n
}
var f1 = new Fn;
// 1.getX执行时,.前面是f1
// 2.console.log(`${this.x}`) --> console.log(`${f1.x}`)
// 3.f1的私有属性有x,即值为100
f1.getX()
// 1.getX执行时,.前面是f1.__proto__即Fn.prototype
// 2.console.log(`${f1.__proto__.x}`) --> console.log(`${Fn.prototype.x}`)
// 3.f1.__proto__指向,Fn构造函数的原型Fn.prototype,Fn.prototype对象上没有属性x,继续往上一级Object的原型对象上查找,Object的原型对象也没有x属性,即值为undefined
f1.__proto__.getX()
// 1.setX执行时,.前面是Fn.prototype
// 2.this.x = n --> Fn.prototype.x = n
// 3.Fn.prototype对象上没有属性x,即直接在Fn.prototype对象上增加x属性,值为300
Fn.prototype.setX(300)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 场景四 apply和call调用
核心:apply和call调用,this指向参数中的对象
var name = 'f';
function fn(){
console.log(this.name);
}
var f1 = {
name:'f1',
}
var f2 = {
name:'f2',
}
fn.call(f1);// f1
fn.call(f2);// f2
fn() // f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 场景五 匿名函数的调用
核心:匿名函数调用,指向的是全局对象 window
,自执行函数中 this
的永远是 window
//①先用()包起来,然后再后面跟 (参数)
(function(data){
console.log(this, data);
})("222");
//②先后面跟(参数),然后再()包起来
(function(data){
console.log(this, data);
}("333"));
//③正常函数格式,前面加 !|~|+|-
!function(data){
console.log(this, data);
}("444");
~function(data){
console.log(this, data);
}('555')
+function(data){
console.log(this, data);
}('666')
-function(data){
console.log(this, data);
}('777')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 场景六 定时器中的调用
核心:定时器中的调用,this指向的是全局变量window
var name = 'f';
var fn = setInterval(function(){
var name = 'f1';
console.log(this.name); // f
clearInterval(fn);
},500);
1
2
3
4
5
6
2
3
4
5
6
# 场景七 箭头函数中的调用
核心:箭头函数内部的 this 是词法作用域,由上下文确定
箭头函数的this跟外层function的this一致,外层function的this指向谁,箭头函数的this就指向谁,如果外层不是function则指****向window
var obj={
id:123,
testFun:function(){
var a= ()=>console.log(this)
a();
}
}
//testFun的this指的是obj,则箭头函数的this指向obj。
obj.testFun()
//testFun的this指向window,箭头函数的this指向window。
obj.testFun.apply(null)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 案例一
说明
预解释步骤:首先声明变量,然后自上而下执行代码
函数执行步骤:首先形参赋值,然后预解释
var num = 20
var obj = {
num: 30,
fn:(function(num){
this.num *= 3
num += 15
var num = 45
return function() {
this.num *= 4
num += 20
console.log(num)
}
})(num) // 把全局变量num的值20赋值给自执行函数的形参,而不是obj下的30,如果想是obj下的30,我们需要写obj.num
}
var fn = obj.fn
fn()
obj.fn()
console.log(window.num, obj.num)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18