普通函数中的this
1、this总是代表他的直接调用者(js的this是执行上下文),例如obj.func,那么func中的this就是obj,this的指向在函数创建的时候决定不了,调用的时候才能决定。它遵循谁调用就指向谁
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a);
}
}
}
o.b.fn();
2、在默认情况下(非严格模式下,未使用‘use strict’),没找到直接调用者,则this指的是window(约定俗成)
function a(){
var name = "javascript";
console.log(this.name);
console.log(this);
}
a();
3、在严格模式下,没有直接调用者的函数中的this是undefind
"use strict"
function a(){
var name = "javascript";
console.log(this);
}
a();
4、使用call,apply,bind(ES5新增)绑定的,this指的是绑定的对象
var name = 'sally';
function sayName(){
return this.name;
}
function sayName2(){
return this.name
}
var o = {
'name':'John',
sayName:sayName,
sayName2:sayName2.bind(window)
};
console.log(o.sayName());
console.log(o.sayName2());
在使用 this 时,为了避坑,你要谨记以下三点:
- 当函数作为对象的方法调用时,函数中的 this 就是该对象;
- 当函数被正常调用时,在严格模式下,this 值是 undefined,非严格模式下 this 指向的是全局对象 window;
- 嵌套函数中的 this 不会继承外层函数的 this 值。
箭头函数中的this
箭头函数有两大要点:
1、箭头函数中,call 和 apply 会忽略掉 this 参数。
这其实是“表象”,实际上是因为箭头函数的 this 是指向父级的 this,因为箭头函数自身没有 this,所以无法修改自身的 this,从而言之 “忽略”。
var a = {say: function() {
var fn = (() => {
console.log(this)
}).bind(window)
fn()
}}
a.say()
2、箭头函数的 this ,永远是跟随父级的 this 的。
箭头函数的 this 是从当前箭头函数逐级向上查找 this,如果找到了,则作为自己的 this 指向,如果没有则继续向上查找。而父级的 this 是可变的,所以箭头函数的 this 也可跟随父级而改变。
var flag = "996";
function person(fg) {
let o = new Object();
o.flag = fg;
o.getVal = () => {
console.log(this);
};
return o;
}
let pp = new person("251");
pp.getVal();
var x = 11;
var obj = {
x: 22,
methods: {
x: 33,
// say: function() {
// console.log(this.x)
// },
say2: () => {
console.log(this.x);
},
},
};
obj.methods.say2();
由于箭头函数绑定了词法作用域,它返回上一级函数调用的this绑定。因此,想修改箭头函数“本身”的 this 是做不到的,但是可以采用变更父级的 this 来达到变更子箭头函数的 this。比如:通过使用bind改变父级inner函数的this,来达到改变子箭头函数getval的this指向。
箭头函数不使用 this 的四种标准规则,而是根据外层(函数或者全局)作用域来决 定 this
function outer() {
var inner = function () {
var obj = {};
obj.getVal = () => {
console.log('====================================');
console.log(this);
console.log('====================================');
};
return obj;
};
return inner;
}
outer().bind(outer)().getVal();
箭头函数注意点:
1、typeof 运算符和普通的function一样
var func = (a) => a;
console.log(typeof func);
2、instanceof也返回true,表明也是Function的实例
var func = (a) => a;
console.log(func instanceof Function);
3、this固定,不再善变
function father() {
this.data = [1, 2, 3, 4];
let o = new Object();
o.a = 1;
o.getVal = () => {
console.log(this.data);
};
return o;
}
var ff = new father();
ff.getVal();
function father() {
this.data = [1, 2, 3, 4];
let o = new Object();
o.a = 1;
o.getVal = function () {
console.log(this.data);
};
return o;
}
var ff = new father();
ff.getVal();
4、箭头函数不能用new
var Person = (name, age) => {
this.name = name;
this.age = age;
};
var p = new Person("John", 33);
5、不能使用argument, 可用...rest代替,因为在箭头函数中arguments指向的对象并不是当前函数所属的arguments,而是上级函数的arguments,所以需要将箭头函数转为function
var func = () => {
console.log(arguments);
};
func(123, 4);
var func = (...value) => {
console.log(value);
};
func(55, 6, 7);
思考:
var flag = "996";
function person(fg) {
let o = new Object();
o.flag = fg;
o.getVal = () => {
console.log(this);
};
this.a = 1;
console.log("======aaaaa==============================");
console.log(this);
console.log("====================================");
return o;
}
let pp = new person("251");
pp.getVal();
console.log("====ppppp================================");
console.log(pp);
console.log("====================================");
var flag = 996;
function person(fg) {
let o = new Object();
o.flag = fg;
o.getval = () => {
console.log(this);
};
this.a = 1;
return true;
}
var p2 = new person("251");
console.log(p2.a);
关于new操作符:
1、由于person函数返回的是一个对象(null除外),所以在new的时候返回的是 person函数返回的o对象,并没有返回person函数的this给实例对象。
2、如果person函数返回的是一个【数字、字符串、布尔等】,那么new的时候回忽略返回值,而是仍然会返回person的this给实例对象。
附
x = 11;
var obj = function () {
x = 22;
var methods = function () {
x = 33;
var say = () => {
console.log(this);
};
return say;
};
return methods;
};
obj()()();
var x = 11;
var obj = function () {
var x = 22;
var methods = function () {
var x = 33;
var say = function () {
var x = 44;
console.log(this.x);
};
return say();
};
return methods();
};
obj();