详解JavaScript的this对象

一、this 是什么?

this 是当前运行环境的一个属性,指向最近的对象实例。

二、怎么用?
1、全局
<!DOCTYPE html>
<html lang='zh-CN'>
<head>
    <meta charset="utf-8">
    <title>this</title>
    <script>
        // 全局环境下,等同于 window 对象
        console.log(this === window); // true
        a = 37;
        console.log(window.a); // 37

        this.b = "MDN";
        console.log(window.b)  // "MDN"
        console.log(b)         // "MDN"
    </script>
</head>
<body>
    <h1>打开 Console 看结果!</h1>
</body>
</html>
2、函数中this

函数中的this指向调用他的实例对象。

var obj = {a: 'Custom'};
var a = 'Global';
function whatsThis() {
  return this.a;  
}
// 全局调用,this 指向 window 对象
whatsThis();          // Global
// 强制实例对象obj转换为this
whatsThis.call(obj);  // Custom
whatsThis.apply(obj); // Custom
3、方法中this

方法中的 this 是指向最近的对象实例。

var o = {
    prop: 37,
    f: function () {
        return this.prop;
    }
};
console.log(o.f()); // 37

o.b = { g: independent, prop: 42 };
// g()方法中最近实例是b,实例o是再上一层实例
console.log(o.b.g()); // 42
4、箭头函数中this

箭头函数本身无法与 this 进行绑定,所以箭头函数中使用的this是指向上层作用域。call、bind、apply 对箭头函数中this无效。

// 1、this 指向上层作用域
var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true

var obj = {foo: foo};
console.log(obj.foo() === globalObject); // true

// 2、call、bind 无法改变箭头函数中的 this
console.log(foo.call(obj) === globalObject); // true
foo = foo.bind(obj);
console.log(foo() === globalObject); // true
  • 方法中使用含有this的箭头函数
var obj = {
  bar: function() {
    var x = (() => this);
    return x;
  }
};
// 1、调用方法,this指向对象实例
var fn = obj.bar();
console.log(fn() === obj); // true
// 2、引用方法,this不指向对象实例
var fn2 = obj.bar;
console.log(fn2()() == window); // true
5、原型链上this

原型链上的this也是指向最近对象实例。

var o = {
  f: function() {
    return this.a + this.b;
  }
};
// 对象o是对象p的原型
var p = Object.create(o);
p.a = 1;
p.b = 4;

console.log(p.f()); // 5
6、set、get中this

set、get方法中的this也是指向最近对象实例。

function sum() {
  return this.a + this.b + this.c;
}

var o = {
  a: 1,
  b: 2,
  c: 3,
  get average() {
    return (this.a + this.b + this.c) / 3;
  }
};

Object.defineProperty(o, 'sum', {
    get: sum, enumerable: true, configurable: true});

console.log(o.average, o.sum); // logs 2, 6
7、new与this

new 后面的构造函数,如果没有return语句,就会返回this;如果有,就用返回return语句的对象。

function C(){
  this.a = 37;
}
var o = new C();
console.log(o.a); // logs 37

function C2(){
  this.a = 37;
  return {a:38};
}
o = new C2();
console.log(o.a); // logs 38
8、DOM中this

如果this用在事件回调函数中,那么this指向触发事件的元素。

// 被调用时,将关联的元素变成蓝色
function bluify(e){
  console.log(this === e.currentTarget); // 总是 true

  // 当 currentTarget 和 target 是同一个对象时为 true
  console.log(this === e.target);
  this.style.backgroundColor = '#A5D9F3';
}

// 获取文档中的所有元素的列表
var elements = document.getElementsByTagName('*');

// 将bluify作为元素的点击监听函数,当元素被点击时,就会变成蓝色
for(var i=0 ; i<elements.length ; i++){
  elements[i].addEventListener('click', bluify, false);
}
9、类中this
  • 类方法中this指向调用它的对象实例。
var name = "globalName";
class Example{
    name="className";
    fun(){
        return this.name;
    }
}
// 1、this指向实例对象
let exm = new Example();
console.log(exm.fun());
// 2、使用全局this作为实例对象
let funGlobal = Example.fun;
console.log(exm.fun.call(this)); 
  • 使用bind方法,让类方法中this永远指向类的实例
class Car {
    constructor() {
        this.sayBye = this.sayBye.bind(this);
    }
    sayHi() {
        console.log(`Hello from ${this.name}`);
    }
    sayBye() {
        console.log(`Bye from ${this.name}`);
    }
    get name() {
        return 'Ferrari';
    }
}

class Bird {
    get name() {
        return 'Tweety';
    }
}

const car = new Car();
const bird = new Bird();

// 1、不同实例调用不同结果
car.sayHi(); // Hello from Ferrari
bird.sayHi = car.sayHi;
bird.sayHi(); // Hello from Tweety

// 2、绑定this,结果不会改变
bird.sayBye = car.sayBye;
bird.sayBye();  // Bye from Ferrari
  • 类中this 包含所有非静态方法,静态方法属于类本身属性。
class Example {
    constructor() {
        const proto = Object.getPrototypeOf(this);
        console.log(Object.getOwnPropertyNames(proto));
    }
    first() { }
    second() { }
    static third() { }
}

new Example(); // ['constructor', 'first', 'second']
10、bind()

bind() 方法可以将函数的this 与 某个对象实例进行永久绑定,无需考虑函数的调用方式。已绑定对象无法再次绑定。

function f(){
  return this.a;
}

var g = f.bind({a:"azerty"});
console.log(g()); // azerty

// 已绑定对象无法再次绑定。
var h = g.bind({a:'yoo'}); 
console.log(h()); // azerty

var o = {a:37, f:f, g:g, h:h};
console.log(o.a, o.f(), o.g(), o.h()); // 37, 37, azerty, azerty
三、参考文档

相关文章

kindeditor4.x代码高亮功能默认使用的是prettify插件,prett...
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代...
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小