事件调用环境
谁触发事件,函数里面的this指向的就是谁。
.box1, .box2 {
width: 100px;
height: 100px;
border: 1px solid black;
background: #0A8CD2;
position: relative;
left: 0;
transition: 1s;
}
<div class="box1"></div>
<div class="box2"></div>
let box1 = document.querySelector('.box1');
let box2 = document.querySelector('.box2');
box1.onclick = move;
box2.onclick = move;
function move() {
this.style.left = '100px';
}
全局环境
- 浏览器
windowconsole.log(this); // Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
- node
module.exportsconsole.log(this === module.exports); // true
函数内部
- this最终指向的是调用它的对象
- 普通函数直接调用与window调用
- 对象中的函数直接调用与window调用
.box1, .box2 {
width: 100px;
height: 100px;
border: 1px solid black;
background: #0A8CD2;
position: relative;
left: 0;
transition: 1s;
}
<div class="box1"></div>
<div class="box2"></div>
let box1 = document.querySelector('.box1');
let box2 = document.querySelector('.box2');
box1.onclick = move;
box2.onclick = move;
function move() {
console.log(this);
this.style.left = '100px';
}
move(); // Window; 严格模式下:undefined
window.more() // 使用这个方法调用,严格模式下也是 Window
// var abc = 10;
// console.log(window);
- 函数被多层对象所包含,如果函数被最外层对象调用,this指向的也只是它上一级的对象
- 多层对象中的函数的this指向
- 对象中的函数被赋值给另一个变量
var obj = {
a: 10,
b: function () {
console.log(this);
}
}
obj.b();
window.obj.b();
- 构造函数中的this指向的是实例对象
- 构造函数中的this指向
- new运算符的作用
function fn() {
this.num = 10;
console.log(this);
}
var obj = new fn();
console.log(obj);
/*
1. 调用函数
2. 自动创建一个对象
3. 把创建出来的对象和this进行绑定
4. 如果构造函数没有返回值,隐式返回this对象
*/
function fn() {
this.num = 10;
console.log(this);
}
fn.num = 20;
fn.prototype.num = 30;
fn.prototype.method = function () {
console.log(this.num);
}
var prototype = fn.prototype;
var method = prototype.method;
// 调用环境不同,this的指向不同
// 举例:
// 1.
new fn().method(); // 10
// {}.methods();
// 2.
prototype.method(); // 30
// fn.prototype = {}
/*
var obj = {};
obj.x = 10;
obj.fn = function () {
console.log(this.x);
}
obj.fn(); // 10
// 此写法相当于下面那种写法
var obj = {
x: 10,
fn: function () {
console.log(this);
}
}
*/
// 3.
method(); // undefined
/*
var obj = {};
obj.x = 10;
obj.fn = function () {
console.log(this.x);
}
var abc = obj.fn();
abc(); // Window
*/
- 如果构造函数中有return 如果return的值是对象,this指向返回的对象;如果不是对象,则this指向保持原来的规则。 (null比较特殊)
function fn() {
this.num = 10;
return '';
/*
return 1;
return null;
*/
}
var obj = new fn();
console.log(obj.num); // 10
//
function fn() {
this.num = 10;
return [];
/*
return {};
return function(){};
*/
}
var obj = new fn();
console.log(obj.num); // undefined
箭头函数
- 箭头函数本身是没有this和arguments的,在箭头函数中引用this实际上调用的是定义这个箭头函数的上一层作用域的this。(是上一层作用域,因对象是不能形成独立的作用域的)
let box1 = document.querySelector('.box1');
let box2 = document.querySelector('.box2');
box1.onclick = move;
box2.onclick = move;
function move() {
setTimeout(function () {
this.style.left = '100px';
}, 1000)
}
// Uncaught TypeError: Cannot set property 'left' of undefined
// this是指向window的
// 改进方法
function move() {
var _this = this;
setTimeout(function () {
_this.style.left = '100px';
}, 1000)
}
// 用箭头函数更方便!
let box1 = document.querySelector('.box1');
let box2 = document.querySelector('.box2');
box1.onclick = move;
box2.onclick = move;
function move() {
setTimeout(() => {
this.style.left = '100px';
}, 1000)
}
修改this指向
call(this,a,b,c)
apply(this,[a,b,c])
bind(this,a,b,c)()
var box = document.querySelector('.box'),
a, b, c;
var obj = {
// fn: () => {
// console.log(this);
// }
// 箭头函数在定义的时候就已经决定了this的指向,不能用call等修改
fn: function () {
console.log(this);
}
}
obj.fn.call(box, a, b, c);
obj.fn.apply(box, [a, b, c]);
obj.fn.bind(box)();
<div class="box"></div>