1.在Javascript中,this指向函数执行时的当前对象
function foo() {
console.log( this.a );
}
function doFoo() {
foo();
}
- 该处的执行foo()的时候,执行环境为doFoo函数,而该函数为普通函数,this指向window
2.箭头函数时不绑定this的,它的this来自原其父级所处的上下文
var a = 10
var obj = {
a: 20,
say: () => {
console.log(this.a)
}
}
obj.say() //10
var anotherObj = { a: 30 }
obj.say.apply(anotherObj) //10
- 该代码的obj对象是在全局定义的,故箭头函数say()方法继承其父级所处的上下文,即windows,所以第一个输出仍然是10,后面虽然让say方法指向了另外一个对象,但是仍不能改变箭头函数的特性,它的this仍然是指向全局的,所以依旧会输出10。
- 若为say为普通函数,其this指向指向他所在的对象,即输出obj其中的a的值
3.如果call第一个参数传入的对象调用者是null或者undefined,call方法将把全局对象(浏览器上是window对象)作为this的值
function a() {
console.log(this);
}
a.call(null);
- 输出window对象
- 但若开启了严格模式,null 就是 null,undefined 就是 undefined
'use strict';
function a() {
console.log(this);
}
a.call(null); // null
a.call(undefined); // undefined
var a = 10;
var obj = {
a: 20,
fn: function(){
var a = 30;
console.log(this.a)
}
}
obj.fn(); // 20
obj.fn.call(); // 10
(obj.fn)(); // 20
-
obt.fn.call():
这里call的参数啥都没写,就表示null,我们知道如果call的参数为undefined或null,那么this就会指向全局对象this,所以会打印出 10;
-
(obj.fn)()
:相当于立即执行 obj.fn()
4. 使用new构造函数时,其this指向的是全局环境window
var obj = {
name : 'cuggz',
fun : function(){
console.log(this.name);
}
}
obj.fun() // cuggz
new obj.fun() // undefined
5. 对象不构成单独的作用域
var obj = {
say: function() {
var f1 = () => {
console.log("1111", this);
}
f1();
},
pro: {
getPro:() => {
console.log(this);
}
}
}
var o = obj.say;
o(); //1111 window对象
obj.say(); //1111 obj对象
obj.pro.getPro(); //window对象
- 调用
o()
:注意此时调用的环境是在全局作用域下,f1()
箭头函数继承父级say function()
在全局作用域中,故打印出window;
-
obj.say()
:谁调用say,say 的this就指向谁,所以此时this指向的是obj对象;
-
obj.pro.getPro()
:由于getPro处于pro中,而对象不构成单独的作用域,所以箭头的函数的this就指向了全局作用域window;
6.立即执行函数调用this指向window,对象方法调用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);
}());
}
};
myObject.func();
//bar bar undefined bar
-
func
是由myObject
调用,this指向myObject
,故self
也指向myObject
- 立即执行匿名函数表达式的this指向window 。立即执行匿名函数的作用域处于
myObject.func
的作用域中,在这个作用域找不到self变量,沿着作用域链向上查找self变量,找到了指向 myObject对象的self
7. 对象中若存在立即执行函数会直接执行后销毁
window.number = 2;
var obj = {
number: 3,
db1: (function(){
console.log(this);
this.number *= 4;
return function(){
console.log(this);
this.number *= 5;
}
})()
}
var db1 = obj.db1;
db1();
obj.db1();
console.log(obj.number); // 15
console.log(window.number); // 40
- 输出:
- 一开始在初始化obj对象时,立即执行函数this指向window,此时已经执行
this.number *= 4
,window.number
为8
- 然后执行
db1()
由于返回的是一个普通函数,在全局中调用,this指向window,故window.number
为8*5 = 40
function(){
console.log(this);
this.number *= 5;
}
- 最后执行
obj.db1()
,this指向obj对象,执行返回的函数,obj.number
为3*5 = 15
8.this的指向通常是调用函数的时候确定的,一般指向调用者
var length = 10;
function fn() {
console.log(this.length);
}
var obj = {
length: 5,
method: function(fn) {
fn();
arguments[0]();
}
};
obj.method(fn, 1);
- 调用
fn()
的时候在method方法中执行,对象不构成作用域,故this指向的是window,输出10
-
arguments[0]
为fn(),相当于arguments
调用方法,this指向arguments,而这里传了两个参数,故输出arguments长度为2
9. 注意对象中函数的写法,函数调用的时机
var a = 1;
function printA(){
console.log(this.a);
}
var obj={
a:2,
foo:printA, //此时的printA还没有被调用
bar:function(){
printA(); //已调用
}
}
obj.foo(); // 2
obj.bar(); // 1
var foo = obj.foo;
foo(); // 1
-
obj.foo(),
foo 的this指向obj对象,所以a会输出2;
-
obj.bar(),
printA在bar方法中执行,所以此时printA的this指向的是window,所以会输出1;
-
foo(),
foo是在全局对象中执行的,所以其this指向的是window,所以会输出1;
10.
var x = 3;
var y = 4;
var obj = {
x: 1,
y: 6,
getX: function() {
var x = 5;
return function() {
return this.x;
}();
},
getY: function() {
var y = 7;
return this.y;
}
}
console.log(obj.getX()) // 3
console.log(obj.getY()) // 6
- 匿名函数的this是指向全局对象的,所以this指向window,会打印出3;
- getY是由obj调用的,所以其this指向的是obj对象,会打印出6;
11.
function a(xx){
this.x = xx;
return this
};
var x = a(5);
var y = a(6);
console.log(x.x) // undefined
console.log(y.x) // 6
- 函数a是在全局作用域调用,所以函数内部的this指向window对象,故x的值为window,而window对象中没有x属性,所以会输出undefined
- 当执行y.x时,y为window,并会给全局变量中的x赋值为6,所以会打印出6
12.this绑定的优先级:new绑定 > 显式绑定 > 隐式绑定 > 默认绑定
function foo(something){
this.a = something
}
var obj1 = {
foo: foo
}
var obj2 = {}
obj1.foo(2);
console.log(obj1.a); // 2
obj1.foo.call(obj2, 3);
console.log(obj2.a); // 3
var bar = new obj1.foo(4)
console.log(obj1.a); // 2
console.log(bar.a); // 4