this 指针
this 指针指向
this 存在于执行上下文(executation context),指向属性或方法当前所在的对象。
this 指针案例
// 实际执行的是 window.getName(),window 对象并没有 name 属性
// 严格模式中指向的是 undefined
this === window; // true
function getName(){
var name = "Tate";
console.log(this.name); // undefined
console.log(this); // Window
}
getName();
// this 只是指向当前一层的对象,而不会向上继承
// 调用的是 person.spouse 对象,但 spouse 无 name 属性
var person = {
name: 'Tate',
spouse:{
fn: function(){
console.log(this.name); // undefined
}
}
}
person.spouse.fn();
// 赋值但并未执行函数,相当于执行的是 window.fn()
var person = {
name: 'Tate',
spouse:{
name: 'Snow',
fn: function(){
console.log(this.name); // undefined
console.log(this); // Window
}
}
}
var fn = person.spouse.fn;
fn();
this 指针案例-多层嵌套
// 内层的 this 不指向外部,而指向顶层对象 Window
var person = {
name: 'Tate',
spouse: function () {
console.log(this.name); // Tate
var f2 = function () {
console.log(this); // Window
}();
}
}
person.spouse();
可以用变量来保存当前所引用的对象,如下面例子的 that:
var person = {
name: 'Tate',
spouse: function () {
console.log(this.name); // Tate
var that = this;
var f2 = function () {
console.log(that.name); // Tate
}();
}
}
person.spouse();
ES6 箭头函数(=>)实际上实现方式与上例类似,它本身是没有 this 属性的,所以也就不能用作构造函数,它会捕获其所在(即定义的位置)上下文的 this 值:
var name = 'Tate';
sayName.call({ name: 'Snow' });
// ES6
function sayName() {
setTimeout(() => {
console.log('name:', this.name); // snow
}, 100);
}
// ES5
function sayName() {
var _this = this;
setTimeout(function () {
console.log('name:', _this.name);
}, 100);
}
再看个箭头函数的栗子:
var x = 10;
var obj = {
x: 20,
say: function() {
console.log(this.x)
}
}
obj.say(); // 20
var x = 10;
var obj = {
x: 22,
say: () => {
console.log(this.x); // this 此时指向的是 window
}
}
obj.say(); // 10
this 指针案例-return
一般情况下若返回的是引用类型,则返回该引用类型;若返回的是基本类型,则无影响。
setTimeout(() => {
console.log('name:', this.name);
}, 100);
// ES5
function Person() {
this.name = 'Tate';
// return undefined; // Tate
// return null; // Tate
// return 'Snow'; // Tate
// return [1, 2]; // undefined
// return {name: 'Snow'}; // Snow
return function(){ console.log('Snow'); }; // undefined
}
var p = new Person;
console.log(p.name);
call / apply / bind
function foo(p1, p2) {
console.log(this.name); // Tate
console.log(p1 + p2); // 3
}
var person = {
name: 'Tate'
};
foo.call(person, 1, 2);
foo.apply(person, [1, 2]); // apply 和 call 类似,只是参数不同,立即执行
var bar = foo.bind(person, 1);
bar(2); // bind 绑定指针后并没有立即执行,参数按顺序注入,相当于 bind(person,1,2)
构造函数实例化本质
function Person() {
this.name = 'Tate';
}
var p = new Person();
// new 操作符的操作实际是
var p = {}; // 申明一个空对象
p.__proto__ = Person.prototype; // 将 __proto__ 指针指向 Person 的 prototype,即其原型对象
// Object.setPrototypeOf(p, Person.prototype);
Person.call(p); // 改变 Person 内部 this 指针,指向 p 对象
参考链接
- 彻底理解 js 中 this 的指向,不必硬背 By 追梦子
- this 关键字 By 阮一峰