Javasctipt 的 this
函数的this关键字在JavaScript中的行动与其他言语稍有差别。严厉模态与非严厉模态也有肯定的辨别。在大多数情况下,这个值由函数的挪用体式格局决议。它不能在定义时期经由过程赋值来肯定,而且每次挪用函数时它多是差别的。ES5引入了bind()要领来设置函数this的值,不论它是怎样挪用的,而ES2015引入了箭头函数,它不供应本身的this绑定(它保留了所包括的词法高低文的这个值)。
一、在全局环境中的this
在浏览器环境中
- 直接输出this
console.log(this); // Window
console.log(this === window); // true
console.log(this === Window); // false
window instanceof Window // true
上述效果说明直接输出this时,输出的是它的组织函数,但它实际上是一个实例;
'use strict'
console.log(this); // undefined
严厉情势下,全局的this指向undefined
在node环境中
- 直接输出this
console.log(this); // {}
严厉和非严厉情势都是 {}
二、函数中的this
直接在全局环境中挪用,而不是作为某个对象的属性或要领
function fn() {
return this;
}
let obj = {
a: 1,
b: fn
}
fn() // node: global , browser: window
let objFn = obj.b;
objFn(); // node: global , browser: window
// 箭头函数
let obj2 = {
a: 2,
b: () => this
}
let obj2Fn = obj2.b;
obj2Fn(); // node: global , browser: window
// 马上实行函数
!function(){
console.log(this === window) // true
}()
let obj = {
say: function() {
console.log(this === window) // true
}()
}
obj.say;
let str = 'windows'
let o = {
str: 'o',
methods: {
str: 'methods',
fn: function () { console.log(this.str) },
arrowFn: function() { // IIFE
let fn = () => { console.log(this.str) }
return fn;
}()
}
}
o.methods.arrowFn(); // undefined ;此时,this指window;而用let声明的str变量不会添加到window对象上去,所认为undefined;
在严厉情势下
function fn() {
'use strict'
return this;
}
fn() // undefined
作为对象的属性挪用
function fn() {
return this;
}
let obj1 = {
a: 1,
b: fn
}
let obj2 = {
a: 2
}
obj2.b = obj1.b;
obj1.b(); // {a: 1, b: ƒn}
obj2.b(); // {a: 2, b: ƒn}
// 箭头函数
let obj1 = {
a: 1,
b: () => this
}
let obj2 = {
a: 2
}
obj2.b = obj1.b;
obj1.b(); // node: global , browser: window
obj2.b(); // node: global , browser: window
经由过程call 和 apply 要领挪用
假如函数在其主体中运用this关键字,则可以运用call()或apply()要领将其值绑定到挪用的特定对象
function add(c, d) {
return this.a + this.b + c + d;
}
var o = {a: 1, b: 3};
add.call(o, 5, 7); // 16
add.apply(o, [10, 20]); // 34
// 经常使用的例子
function bar() {
console.log(Object.prototype.toString.call(this));
}
bar.call(7); // [object Number]
bar.call('foo'); // [object String]
经由过程 bind 要领来绑定this
function fn() {
return this.a;
}
let k = fn.bind(null);
k(); // undefined
//此时this === window
let g = fn.bind({a: 1});
g(); // 1
let m = fn.bind({a: 2});
m(); // 2
let h = g.bind({a: 3}); // bind只会绑定一次
h(); // 1
// 一般返回值
let obj = {
a: 1,
say: (function() {
let _say = function() {
console.log(this.a);
}
return _say;
})()
}
obj.say(); // 1
// bind obj
var obj = {
say: (function() {
let _say = function() {
console.log(this === window);
}
return _say.bind(obj);
})()
}
obj.say(); // true
// bind的简朴完成
Function.prototype.myBind = function(context){
self = this; //保留this,即挪用bind要领的目的函数
return function(){
return self.apply(context,arguments);
};
};
let g1 = fn.myBind({a: 1})
g1(); // 1
let h1 = g1.myBind({a: 3})
h1(); // 报错,
道理
this指的是函数运转时地点的环境,实行高低文
JavaScript 将对象存储在内存中,会将存储的地点赋给我们所说明的变量;
var o = {a: 5};
//内存中会如许存储 o => a => {
// foo: {
// [[value]]: 5
// [[writable]]: true
// [[enumerable]]: true
// [[configurable]]: true
// }
//}
var f = function () {}
var m = {a: f}
// 当a的值是一个函数的时刻,就会变成以下情势:
//内存中会如许存储 o => a => {
// foo: {
// [[value]]: f的地点
// [[writable]]: true
// [[enumerable]]: true
// [[configurable]]: true
// }
//}
this的作用
由上面可以看出,因为函数零丁存储,可以零丁运转,运转在差别的高低文中。但要有一个机制来示意它,this就是这个作用,可以指向当前函数的运转环境;
箭头函数道理的思索
箭头函数又和上文说的内容不符合。实在细致想一想,它是个语法糖,等同于给函数运用了bind要领,绑定函数的父作用域实行环境
let str = 'windows'
let o = {
str: 'o',
methods: {
str: 'methods',
fn: function () { console.log(this.str) },
arrowFn: () => { console.log(this.str) }
}
}
let str = 'windows'
let o = {
str: 'o',
methods: {
str: 'methods',
fn: function () { console.log(this.str) },
arrowFn: function() {
let fn = () => { console.log(this.str) }
return fn;
}
}
}
o.methods.fn(); // methods
o.methods.arrowFn()(); // methods; 注重辨别上面的马上实行函数