this-函数上下文
this的指向不仅由定义函数的方式和位置决定的,同时还严重受到函数调用方式的影响
作为函数直接被调用
- 非严格模式:this指向全局上下文(window)
- 严格模式:this指向undefined
function fn1() {};
fn1();
const fn2 = function () {};
fn2();
(function () {})()
作为方法被调用
- this指向调用对象(即宿主对象)
let my = {};
my.fn = function () {return this};
my.fn(); // my
作为构造函数调用
- this指向新创建的对象
function Fn() {
this.my = "11"
name = "1"
}
const fn = new Fn();
name; // "1"
fn.name; // undefined
fn.my; // "11"
new操作符实现过程
- 在内存中创建一个新对象
- 这个对象内部的 [[ Prototype ]] 特性被赋值为构造函数的 prototype 属性
- 构造函数内部的 this 的指向被修改为这个新对象
- 执行构造函数内部的代码
- 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的对象
使用apply和call方法调用
- 第一个参数不传或者传undefined,this默认指向调用对象
- 反之,this指向第一个参数
const my = {};
function fn() {
return this;
}
fn(); // window
fn.call(); // window
fn.call(1); // Number {1}
fn.call(my, 1, 2, 3); // my
fn.apply(); // window
fn.apply(1); // Number {1}
fn.apply(my, [1, 2, 3]); // my
解决函数上下文问题
使用箭头函数绕过函数上下文
- 箭头函数没有单独的this值,它的this与声明所在的上下文相同
const fn = {
show: () => {
return this
}
}
let newFn = {};
newFn.fn = fn.show;
fn.show(); // window
newFn.fn(); // window
使用bind方法
- bind不会改变原始函数,而是创建一个全新的函数
- 创建的新函数被绑定到指定对象上。不管如何调用该函数,this均被设置为对象本身。被绑定的函数与原函数行为相同
function fn() {
return this;
}
const newFn = fn.bind({});
newFn(); // {}
newFn().call(window); // {}
fn(); // window
参考
《JavaScript忍者秘籍2》