一、 this 的概念
this就是指针, 指向我们调用函数的对象; this是JavaScript中的一个关键字,它是函数运行时,在函数体内自动生成的一个对象,只能在函数体内部使用。
1. 全局环境中this指向全局变量(window);
2. 函数中的this,由调用函数的方式来决定,
(1)如果函数是独立调用的,在严格模式下(use strict)是指向undefined的,在非严格模式下,指向window;
(2)如果这个函数是被某一个对象调用,那么this指向被调用的对象;
3. 构造函数与原型里面的this
构造函数里的this以及原型里的this对象指的都是生成的实例;(由new决定的)
通过new操作符可以初始化一个constructor的指向,new的作用就是创建一个对象的实例,constructor也就指向了一个新的执行环境“在这个对象之中”;
4. 箭头函数按词法作用域来绑定它的上下文,所以this 实际上会引用到原来的上下文。
(箭头函数会保持它当前执行上下文的词法作用域不变,而普通函数则不会,箭头函数从包含它的词法作用域中继承了this的值)。
二、例题
/*-----------题目一-------------------*/
var obj = {
a: 10,
b: this.a + 10, //这里的this指向window(全局),a为undefined ==> undefined + 20 = NaN
fn: function () {
return this.a;
}
}
console.log(obj.b); //NaN
console.log(
obj.fn(), //10
obj.fn //fn
);
/**-------------题目二 ----------------*/
var a = 20;
var obj = {
a: 10,
getA: function () {
return this.a;
}
}
console.log(obj.getA()); //10
var test = obj.getA;
console.log(test()); //20 独立调用test
/*-----------题目三-------------------*/
var a = 5;
function fn1(){
var a = 6;
console.log(a); //6
console.log(this.a); //5
}
function fn2(fn) {
var a = 7;
fn();
}
var obj = {
a: 8,
getA: fn1
}
fn2(obj.getA);
/*-----------题目四-------------------*/
function fn( ) {
'use strict';
var a = 1;
var obj = {
a: 10,
c: this.a + 20 //严格模式下,a指向undefined嘛,undefined.a报错
}
return obj.c;
}
console.log(fn()); //输出报错==》 a undefined
/*-----------题目五-------------------*/
// 声明一个构造函数
function Person(name, age) {
this.name = name;
this.age = age;
console.log(this); //与下面的this是一样的,都是Person
}
// Person(); //this 指向window
Person.prototype.getName = function () {
console.log(this); //与上面的this是一样,都是Person
};
var p1 = new Person("test", 18);
p1.getName();
/*--------- 题目六 -----*/
var obj = {
foo: "test",
fn: function(){
var mine = this;
console.log(this.foo); //test
console.log(mine.foo); //test
(function(){
console.log(this.foo); //undefined
console.log(mine.foo); //test
})();
}
};
obj.fn();
/**
(1) 在外部函数中, this 和 mine两者都指向了obj,因此两者都可以正确地引用访问foo;
(2) 在内部函数中, this不再指向obj, this.foo 没有在内部函数中被定义,
而指向到本地的变量mine保持在范围内,并且可以访问(在ES5之前,内部函数的this将指向全局的
window对象; 则作为ES5,内部函数中的this是未定义的。)
*/
/* --------- 题目七 ----------- */
function foo(){
console.log(this.a);
}
var a = 2;
var o = {
a:3,
foo: foo
};
var p = { a:4 };
o.foo(); //3
(p.foo = o.foo)(); //2
/**
相当于:
function w(){
p.foo = o.foo;
}
w();
此时的constructor指向window,调用这个w,这个w是在window下创建的,相当于
调用window.w(),所以constructor指向window。
*/
p.foo = o.foo;
p.foo(); //4 函数由p执行,那么constructor指向的就是对象p,谁调用就指向谁0.0
//this也就指向p, 因此this.a === p.a
/* --------- 题目八 ----------- */
//明确绑定的优先权要高于 隐含绑定
function foo() {
console.log(this.a);
}
var obj1 = {
a: 3,
foo: foo
};
var obj2 = {
a: 5,
foo: foo
};
obj1.foo(); //3
obj2.foo(); //5
obj1.foo.call(obj2); //5
obj2.foo.call(obj1); //3
// new 绑定的优先级高于隐含绑定,并且new 和call/ apply不能同时使用,所以
// new foo.call(obj1)是不允许的,也就是不能直接对比测试 new绑定 和 明确绑定
/* --------- 题目九 有意思的一题----------- */
function test(arg) {
this.x = arg;
return this;
}
/**
var x = test(5); --> window.x = window.test(5);
*/
var x = test(5); //此时 x = window, y = undefined
var y = test(6); //此时 x = 6, y = window , 后面申请的x会覆盖掉第一次在this.x 生成的window.x
console.log(x.x); //undefined, 实际上是6.x 是undefined
console.log(y.x); //6 实际上是window.x 也就是6
/* --------- 题目十 ----------- */
var obj = {
data: [1,2,3,4,5],
data2: [1,2,3,4,5],
fn: function () {
console.log("--test--");
console.log(this); //{data: Array(5), data2: Array(5), fn: ƒ, fn2: ƒ}
return this.data.map(function (item) {
console.log(this); // --> window
return item * 2;
});
},
fn2: function () {
console.log("---test2---");
console.log(this); //{data: Array(5), data2: Array(5), fn: ƒ, fn2: ƒ}
return this.data2.map(item=>{
console.log(this); // --> obj {data: Array(5), data2: Array(5), fn: ƒ, fn2: ƒ}
return item * 2;
});
}
};
obj.fn();
obj.fn2();