this指向
全局环境
window
<script type="text/javascript">
console.log(this); // 全局环境 window
</script>
事件处理函数
DOM事件处理函数
<div id="box">div</div>
<script type="text/javascript">
var box = document.getElementById('box');
box.onclick = function () {
console.log(this); // 事件处理函数中的this,该事件由谁触发,this指向的就是谁
}
</script>
内联事件处理函数
<div id="box1" onclick="console.log(this)">div1</div><!-- this: <div id="box1" onclick="console.log(this)">div1</div> 指向触发事件的元素-->
<div id="box2" onclick="( (function (){console.log(this)})() )">div2</div><!-- this: window -->
函数内部
函数直接执行
非严格模式下:
1、默认指向全局对象
(1)浏览器
(2)node
a: node交互界面中;
b: js文件中;
node_this.js 文件中直接console.log(this);用node方式打开输出{}console.log(this === module.exports);输出true
node交互界面中直接输入this 输出的才是gobal
严格模式下(前面省略window,浏览器严格模式支持)
undefined
call,apply,bind 把this的值从一个执行环境传入另一个执行环境,call和apply的参数差异,如果传入的不是对象会调用相对的构造函数,进行隐式转换
<script type="text/javascript">
function fn() {
console.log(this);
}
var fn1 = fn.bind(1);
fn1(); // Number {1}__proto__: Number[[PrimitiveValue]]: 1
</script>
call
<script type="text/javascript">
function fn(m,n) {
console.log(this.a,m,n); // 1 2 3
}
fn.call({a:1},2,3);
/* 函数.call 会直接调用该函数
call的第0个参数就是函数执行时候的this
后面的参数是函数执行的时候的参数
*/
</script>
bind 返回一个新函数,内部this指向被修改,只会改变一次
<script type="text/javascript">
function fn() {
console.log(this.a);
}
fn.bind(); // 没有输出 函数.bind 改变this指向,并不调用函数
var fn1 = fn.bind({a:1});
console.log(fn1); // fn() {console.log(this.a);}
fn(); // undefined 并不会改变原有fn的指向
fn1(); // 1
var fn2 = fn.bind({a:2});
var fn3 = fn.bind({a:3});
fn2(); // 2
fn3(); // 3
var fn4 = fn1.bind({a:4}); // fn1该指向只能改一次
fn4(); // 1
</script>
箭头函数内部
与定义时的环境中this一致
点击元素定时改变
<div id="box">box</div>
<script type="text/javascript">
var box = document.querySelector('#box');
box.onclick = function () {
setTimeout(()=>{
this.style.backgroundColor = 'red';
},500);
// 箭头函数被定义的时候指向的是box,所以里面的this就指向box
}
</script>
bind,call不能修改其内部指向
<script type="text/javascript">
var fn = ()=>{
console.log(this);
};
var fn1 = fn.bind({});
fn1(); // window
</script>
全局中定义箭头函数
全局对象
对象内函数定义箭头函数
<script type="text/javascript">
var a = 1;
var obj = {
a: 2,
fn1: ()=>{
console.log(this.a); //this指向window
},
fn2: function () {
console.log(this.a); //this指向obj
}
};
obj.fn1(); // 1 定义时的环境和obj所在环境一样 this指向window
obj.fn2(); // 2 obj调用 this指向obj
</script>
对象内函数返回箭头函数
<script type="text/javascript">
var a = 1;
var obj = {
a: 2,
fn1: function () {
console.log(this.a); // 2
return function () {
console.log(this.a); // 1
}
},
fn2: ()=>{
console.log(this.a); // 1
return ()=>{
console.log(this.a); // 1
}
}
};
// obj.fn1()(); // 1 等同于下面两行代码 obj.fn1()返回的是一个函数 obj.fn1()()是window调用
var innerFn1 = obj.fn1();
innerFn1(); // 1
// obj.fn2()(); // 1
var innerFn2 = obj.fn2();
innerFn2(); // 1
</script>
对象方法内部
当函数作为对象里的方法被调用时:调用该函数的对象
<script type="text/javascript">
var a = 1;
var obj = {
a: 2,
fn: function () {
console.log(this.a);
}
}
obj.fn(); // 2 this指向调用该函数的对象
obj.fn.bind({a: 'haha'})(); // haha
</script>
对象后续附属上的方法调用:调用该函数的对象
<script type="text/javascript">
var obj = {
a: 1
}
var fn = function () {
console.log(this.a);
}
obj.fn = fn;
obj.fn(); // 1 this指向调用该函数的对象
var fn1 = ()=>{
console.log(this.a);
}
obj.fn1 = fn1;
obj.fn1(); // undefined this指向window
</script>
作为函数内嵌套多层的方法调用:就近绑定
<script type="text/javascript">
var a = 1;
var obj = {
a: 2,
b: {
a: 3,
fn: function () {
console.log(this.a);
},
fn1: ()=>{
console.log(this.a);
}
}
}
obj.b.fn(); // 3 this指向调用该函数的对象b
var temp = obj.b.fn; // temp赋值为函数,并没有调用执行
temp(); // 1 this指向调用该函数的对象window
obj.b.fn1(); // 1 this指向定义该函数时的环境window
</script>
构造函数中
构造函数中没有显示return
<script type="text/javascript">
function Fn() {
this.a = 1;
}
var f = new Fn();
console.log(f); // Fn {a: 1} this指向new关键字创建实例化之后的实例f
</script>
构造函数中显示return
return 对象
<script type="text/javascript">
function Fn() {
this.a = 1;
return {};
}
var f = new Fn();
console.log(f); // {} return非null的对象,实例化的结果就是返回出的对象
</script>
return 非对象
<script type="text/javascript">
function Fn() {
this.a = 1;
return 2;
}
var f = new Fn();
console.log(f); // Fn {a: 1} return非对象,实例化的结果就是new的实例
</script>
原型链上函数
调用该函数的对象
<script type="text/javascript">
var p = {
a: 1,
fn: function () {
console.log(this.a);
}
}
var c = Object.create(p); // 以p为模板创建c
console.log(c); // {}__proto__: Object
console.log(c.a); // 1 一个对象上面没有函数,会找proto
console.log(c.__proto__); // {a: 1}
c.fn(); // 1
</script>
getter 和 setter中
get访问
set设置
<script type="text/javascript">
var obj = {
n: 1,
m: 2,
get sum() {
console.log('正在访问sum...');
return this.n + this.m;
},
set sum(v) { // 必须有一个参数 否则报错
console.log('正在设置sum...');
this.n = v/2;
this.m = v/2;
}
}
console.log(obj.sum); // 3
obj.sum = 40;
console.log(obj.n); // 20
</script>