Is it an arrow function? - If the relevant execution context is created by an arrow function then do nothing, meaning this will be whatever it was set by the wrapping execution context.
Was the function called with new?
When invoking a function with the new key word the engine will do some things for us:
Create a new object and set this to reference it.
Reference that object’s __proto__ (called [[Prototype]] in the spec) to the function’s prototype object.
Return the newly created object (this).
So for our purpose to determine what this is, we know it will be a new object that was created automatically just by invoking the function with the new key word.
Was the function called with call / apply or bind? - Then set this to whatever passed as the first argument.
Was the function called as an object method - Then set this to the object left to the dot or square brackets.
Is strict mode on? - Then this is undefined
default case - this will reference the global / window.
function foo(){
// not a real syntax!!! ⚠️
let message = if(foo in myObj) "Hello" else "There"
console.log(message)
}
let myObj = {
foo
};
myObj.foo() // Hello
foo() // There
Type ".help" for more information.
> function logThis(){
... console.log(this);
... }
undefined
>
> const myObj = {
... logThis
... }
undefined
>
> myObj.logThis()
{ logThis: [Function: logThis] }
undefined
Result - window.
Explanation:
Is logThis an arrow function? - No.
Was logThis called with new? - No.
Was logThis called with call / apply / bind? - No.
Was logThis called as an object method? - No.
Is strict mode on? - No.
default case - window (or global).
const logThis = () => {
console.log(this);
}
const myObj = {
foo: logThis
}
myObj.foo()
Result - window.
Explanation:
Is logThis an arrow function? - Yes, whatever this set in the wrapping context. In this case the wrapping context is the “Global execution context” which inside it this refers to the window / global object.
OK
function logThis() {
console.log(this);
}
const myObj = { name: "sag1v" }
logThis.apply(myObj)
Result - myObj.
Explanation:
Is logThis an arrow function? - No.
Was logThis called with new? - No.
Was logThis called with call / apply / bind? - Yeas, whatever passed in as the first argument - myObj in this case.
function logThis(){
console.log(this);
}
const someObj = new logThis()
Result - The object created by logThis.
Explanation:
Is logThis an arrow function? - No.
Was logThis called with new? - Yes, then this is an auto created object inside the function.
const logThis = () => {
console.log(this);
}
const btn = document.getElementById('btn');
btn.addEventListener('click', logThis);
Result - window.
Explanation
Is logThis an arrow function? - Yes, whatever this set in the wrapping context. In this case the wrapping context is the “Global execution context” which inside it this refers to the window / global object.
们知道 this 具有 隐式绑定的规则(摘自
function foo() {console.log(this.a)}
var obj = {a: 2, foo};
obj.foo(); // 2
// self.apply(this, finalArgs)
Function.prototype._bind = function(thisObj) {
const self = this;
const args = [...arguments].slice(1);
return function () {
const finalArgs = [...args, ...arguments];
// new.target 用来检测是否是被 new 调用
if(new.target !== undefined) { new.target !=== undefined;; return this;;;
// this 指向的为构造函数本身
var result = self.apply(this, finalArgs);
// 判断改函数是否返回对象
if(result instanceof Object) {
return reuslt;
}
// 没有返回对象就返回 this
return this;
} else {
// 如果不是 new 就原来的逻辑
return self.apply(thisArg, finalArgs);
}
}
}
prototype .call2
// 第一版
Function.prototype.call2 = function(context) {
// 首先要获取调用call的函数,用this可以获取
context.fn = this;
context.fn();
delete context.fn;
}
// 测试一下
var foo = {
value: 1
};
function bar() {
console.log(this.value);
}
bar.call2(foo); // 1
unction.prototype.apply = function (context, arr) {
var context = Object(context) || window;
context.fn = this;
var result;
if (!arr) {
result = context.fn();
}
else {
var args = [];
for (var i = 0, len = arr.length; i < len; i++) {
args.push('arr[' + i + ']');
}
result = eval('context.fn(' + args + ')')
}
delete context.fn
return result;
}
Array(1) // Array(1) // Array(1)
const a = {
foo: 'bar',
fn () {
console.log(this)
}
}
const fn = a.fn
a.fn();
fn()
const a = {
foo: 'bar',
fn () {
console.log(this)
}
}
const fn = a.fn
a.fn();
fn()
vendor.91416a6e.js:1 {foo: 'bar', fn: ƒ}
vendor.91416a6e.js:1
const o1= {
text: '01',
fn: function() {
return this.text
}
}
const o2 = {
text: '02',
fn: o1.fn,
}
o2.fn()
call/apply
bing
function Foo() {
this.user = ''
return {}
}
const user =new Foo()
console.log(user.user);
arrow function 词法作用域
···
function foo() { return a => { console.log(this.a) } }
const obj1= { a:2 }
const obj2= { a:3 } const bar = foo.call(obj1); console.log(bar.call(obj2)); ···
========> arrow 无法更改 binding