全局的 this(浏览器)
console.log(this.document === document); //true
console.log(this === window); //true
this.a = 37; // 相当于创建了一个全局变量 a
console.log(window.a); //37
一般函数的 this(浏览器)
function f1() {
return this;
}
f1() === window; //true, global object
这里在浏览器就是 window, 如果是 node 中就是 global 全局对象
------------------
严格模式下: 一般函数调用的 this 是指向 undefined
function f2() {
"use strict"
return this;
}
f2() === undefined; //true
作为对象方法的函数 this
更常见的使用 this 的时候是将作为对象方法去用
函数如果作为对象的属性,比如
var o = {
prop:37,
f:function() {
return this.prop;
}
};
console.log(o.f()); //logs 37
o 有一个属性 f, 值是一个函数, 这样一种方式也叫做对象的方法.
这种作为对象的方法去调用的时候,
比如 o.f() 调用的情况下, this 一般指向对象 o,就相当于 return o.prop
所以返回 37
-------------------------------
上面这种是定义成函数字面量的这种对象,
如果这里定义一个对象 o, 一个独立的 independent 函数, 比如
var o = {prop:37},
function independent() {
return this.prop
}
o.f = independent;
console.log(o.f()) // 37
如果直接调用 independent 函数的话, 里面的 this 指向浏览器里的window
如果通过赋值方式临时创建一个属性 f, 并且指向为这个函数对象的时候,拿到 37
所以这里不是看函数是怎么创建的, 而是只要将该函数作为对象的方法去做 o.f 调用的话
这个 this 就指向该对象
对象原型链上的 this
创建一个对象 o, 里面有一个属性 f, 并且函数作为对象属性的值;
再创建一个对象 p, 该对象是空对象, 并且他的原型指向 o
通过 p.a 和 p.b 创建对象上的属性,
调用原型上的方法的时候, this.a 和 this.b 仍然取到对象上的 a 和 b
这里注意的是 p 的原型才是 o
所以调用 p.f 的时候调用的对象原型链上 o 这个函数上的属性f
var o = {f:function() { return this.a + this.b }};
var p = Object.create(o);
p.a = 1;
p.b = 4;
console.log(p.f()) //5
get/set 方法与 this
也指向 get 和 set 方法所在的对象里面
构造器中的 this
正常如下调用是指向全局对象, 在浏览器里是 window
function MyClass() {
this.a = 37;
}
但是如果用 new 把它作为构造器来调用的话,
这里 this 指向原型为 MyClass.prototype 属性这样一个空对象
调用的时候由于 this.a = 37赋值, 所以最后的 this 作为返回值,
所以 o 就有 a 属性
var o = new MyClass();
console.log(o.a) //37
类似
function C2() {
this.a = 37;
return { a: 38 }
}
这时函数里有了 return 语句, 返回值返回一个对象
那么这时o.a 就不是 37 了
o = new C2();
console.log(o.a) //38
call / apply 方法与 this
除了不同的调用方式以外, 每一个函数对象也有一些方法可以去修改函数执行时的 this
function add(c,d) {
return this.a + this.b + c + d;
}
var o = {a:1, b:3};
add.call(o,5,7); // 1+3+5+7 = 16
add.apply(o,[10,20]); //1+3+10+20 = 34
定义一个变量 o 有两个属性 a 和 b,
通过对象的 call 方法
(第一个参数是想作为 this 的对象,
这里是 o, 5 和 7 是想要添加的参数, 5 赋值给 c, 7 赋值给 d)
最终调用的结果是 16
call 和 apply 基本没差别, 差别在于传参方式.
何时用 call 和 apply?
function bar() {
console.log(Object.prototype.toString.call(this))
}
这里想调用Object.prototype.toString, 但是想把 this 指定的时候
bind方法与 this
function f() {
return this.a
}
var g = f.bind({a:"test"});
console.log(g()); //test
有一个函数对象 f,
通过 bind 方法中有一个参数对象 a,
这个对象就是想将某一个对象作为 this 的时候, 来传入的对象
这样就拿到一个新的 g 对象, 这个 g 对象在调用的时候
就已经指向了 bind 参数所以拿到 a 的 test
var o = {a:37, f: f,g : g};
console.log(o.f(),o.g()) //37, test