Dies zeigt auf: 1. Gewöhnliche Funktionen oder als Objektattribute, die auf das Fensterobjekt zeigen. 2. Bei der Ereignisbindung zeigt es auf das Element des gebundenen Ereignisses. 3. Im Konstruktor zeigt es auf die Instanz der Klasse. 4. Zeigen Sie in der Pfeilfunktion auf „This“ im nächstgelegenen übergeordneten Kontext. 5. Zeigen Sie in „call/apply/bind“ auf den ersten übergebenen Parameter.
Die Betriebsumgebung dieses Tutorials: Windows7-System, Javascript-Version 1.8.5, Dell G3-Computer
Der this
-Zeiger in JavaScript
ist unterteilt in folgende Situationen: JavaScript
中this
指向分为以下几种情况:
call/apply/bind
指定下面我们来进行一一介绍
this
取决于方法执行前面是否有“点”,有“点”的话,“点”前面是谁this
就是谁,如果没有点的话,this
指向window
const fn = function () { console.log(this); }; const obj = { name: 'OBJ', fn }; fn(); obj.fn(); const fn1 = obj.fn; fn1();
answer:
1. window 2. {name: 'OBJ', fn: function() {console.log(this)}} // obj 3. window
可以看到函数作为对象的属性被调用的时候,其this
指向调用该函数的对象,否则其this
指向window
在进行事件绑定的时候,事件绑定函数中的this
是绑定事件的元素:
// 假设页面中有id为button的button元素 // var x = 100; window.x = 100; const fn = function () { console.log(this.x); }; const obj = { x: 200, fn }; const $button = document.getElementById('button'); $button.x = 300; obj.fn(); const fn1 = obj.fn; fn1(); $button.addEventListener('click', fn); $button.addEventListener('mouseenter', obj.fn); $button.addEventListener('mouseleave', function () {obj.fn();});
answer:
1. 200 2. 100 3. 点击button时:300 4. 鼠标移入button时:300 5. 鼠标移出时:200
但是需要注意的是,这里我们是在用户点击时,浏览器帮我们将点击事件的this
指向绑定该事件的DOM
元素。如果通过代码来触发对应的事件的话,我们可以通过call/apply/bind
来指定其this
$button.click.call() // this为window,打印结果为100
new Fn
)构造函数(new Fn
)执行,函数中的this
是当前类的实例,这是new
关键字帮我们做到的:
var x = 100; const Fn = function () { this.x = 200; console.log(this.x); }; const fn = new Fn();
answer:
1. 200
箭头函数中没有自身的this
,所用到的this
都是其最近父级上下文中的this
const fn = function () { console.log(this); setTimeout(() => { console.log(this); }, 1000); setTimeout(function () { console.log(this); }); }; const obj = { x: 100, fn }; obj.fn();
answer:
1. {x:100, fn: function() {...}} // obj 2. window 3. {x:100, fn: function() {...}} // obj
call/apply/bind
改变this
指向为call/apply/bind
传入的第一个参数即为函数的this
:
var x = 100; const obj = { x: 200, y: 200 }; const fn = function () { console.log(this.x); }; fn(); fn.call(obj); fn.apply(obj); const fixedThisFn = fn.bind(obj); fixedThisFn();
answer:
1. 100 2. 200 3. 200 4. 200
call
在执行时,第一个参数为this
指向,之后的参数为fn
执行时的参数apply
在执行时,第一个参数为this
指向,之后的参数为fn
执行时的参数组成的数组,数组的每一项会和fn
的每一个参数进行对应bind
在执行时,第一个参数为预先传入this
指向,之后的参数为实际调用fn
前预先传入的参数,返回值为一个函数fixedThisFn
,fixedThisFn
内部会调用fn
并指定其this
指向为了更深入的理解call/apply/bind
是如何改变函数中this
指向的,下面我们分别模拟实现这三个函数
call/apply/bind
源码实现根据前面的介绍,我们知道:当函数作为对象属性被调用时,this
指向调用该函数的对象
const obj = { x: 100, fn () {console.log(this);} }; obj.fn(); // {x: 100, fn: function() {...}} => obj
利用JavaScript
这个特性,我们可以将执行的函数作为call/apply
的第一个参数context
的属性,然后通过context
来调用该属性对应的函数,函数的this
便指向了context
call
的源码模拟如下:
Function.prototype.myOwnCall = function (context, ...args) { const uniqueKey = new Date().getTime(); // this为调用call方法的函数 context[uniqueKey] = this; // 作为对象的方法被对象调用,this指向该对象context const result = context[uniqueKey](...args); delete context[uniqueKey]; return result; };
到这里,有的小伙伴可能已经发现了,如果call/apply
传入的context
不是对象呢?
首先我们看下mdn
对call
方法的第一个参数的描述:
语法:function.call(thisArg, arg1, arg2, ...)
*thisArg
可选的。在function
函数运行时使用的this
值。请注意,this
可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定null
或undefined
时会自动替换为指向全局对象,原始值会被包装
接下来,我们对myOwnCall
方法的第一个参数做如下处理:
function translateToObject (context) { // 可以通过 == 进行判断 context == null // null == undefined => 2个等号是成立的 // null,undefined => window if (typeof context === 'undefined' || context === null) { context = window; } else if (typeof context === 'number') { // 原始值转换为包装对象 context = new Number(context); } else if (typeof context === 'string') { context = new String(context); } else if (typeof context === 'boolean') { context = new Boolean(context); } return context; }
在myOwnCall
方法中调用该函数:
Function.prototype.myOwnCall = function (context, ...args) { context = translateToObject(context); const uniqueKey = new Date().getTime(); // this为调用call方法的函数 context[uniqueKey] = this; // 作为对象的方法被对象调用,this指向该对象context const result = context[uniqueKey](...args); delete context[uniqueKey]; return result; };
apply
的实现与call
this
sein . Wenn kein Punkt vorhanden ist, zeigt this< /code> auf <code>window
🎜Function.prototype.myOwnBind = function (context, paramsArray) { context = translateToObject(context); const uniqueKey = new Date().getTime(); // this为调用call方法的函数 context[uniqueKey] = this; // 作为对象的方法被对象调用,this指向该对象context const result = context[uniqueKey](...paramsArray); delete context[uniqueKey]; return result; };
Function.prototype.myOwnBind = function (context, ...outerArgs) { const fn = this; return function (...innerArgs) { return fn.call(context, ...outerArgs, ...innerArgs); }; };
this
zeigt auf das Objekt, das die Funktion aufruft, andernfalls zeigt this
auf window
🎜this
in der Ereignisbindungsfunktion das Element, das das Ereignis bindet: 🎜Function.prototype.myOwnBind = (context, ...outerArgs) => (...innerArgs) => this.call(context, ...outerArgs, ...innerArgs);
function fn1 () {console.log(1);} function fn2 () {console.log(2);} fn1.call(fn2); fn1.call.call(fn2); Function.prototype.call(fn1); Function.prototype.call.call(fn1);
this
Points des Klickereignisses auf das DOM
-Element zu übertragen, an das das Ereignis gebunden ist. Wenn das entsprechende Ereignis durch Code ausgelöst wird, können wir seinen this
🎜1. 1 2. 2 3. 什么都不输出 4. 1
new Fn
)new Fn
) wird in der Funktion als Instanz der aktuellen Klasse ausgeführt. Das Schlüsselwort new
hilft uns dabei it:🎜// 1. 首先会将Function.prototype.call作为一个函数来执行它原型上的call方法 // 所以call方法内部: // this => Function.prototype.call // context => fn1 // 通过对象的属性来执行方法改变this指向 // fn1[uniqueKey] = this(Function.prototype.call) // fn1[uniqueKey]() // 执行 Function.prototype.call方法,但是this是context // 2. 在this为fn1的情况下执行Function.prototype.call方法 // 所以call方法内部: // this => fn1 // context => window // 通过对象的属性来改变this指向 // window[uniqueKey] = fn1 // window[uniqueKey]() // 执行fn1(),但是this是window
this
, den this</ Der verwendete Code ist <code>this
im nächsten übergeordneten Kontext🎜rrreee🎜answer:🎜rrreeecall /apply/bind
Change this</code > zeigen auf</strong></h3>🎜Der erste Parameter, der für <code>call/apply/bind
übergeben wird, ist die Funktion this
:🎜rrreee🎜answer:🎜rrreee call
ausgeführt wird, zeigt this
auf den ersten Parameter. Die folgenden Parameter sind die Parameter, wenn fn
ist ausgeführt.apply
ausgeführt wird, zeigt this
auf den ersten Parameter. Die nachfolgenden Parameter sind ein Array, das aus Parametern besteht, wenn fn
wird ausgeführt. Jedes Element im Array entspricht jedem Parameter von fn
this
und die nachfolgenden Parameter sind die Parameter, die im Voraus vor dem tatsächlichen Aufruf von fn
übergeben wurden. Rückgabe Der Wert ist eine Funktion fixedThisFn</. code>. <code>fixedThisFn
ruft intern fn
auf und gibt seinen this
-Zeiger call/apply/bind
den Punkt von this
in der Funktion ändert, simulieren und implementieren wir diese drei Funktionen separat🎜call/ apply/bind
Quellcode-Implementierungthis
Zeigt auf das Objekt das ruft die Funktion auf🎜rrreee🎜Mithilfe der Funktion von JavaScript
können wir die ausgeführte Funktion als ersten Parameter context
von call/apply
> verwenden Attribut und rufen Sie dann die dem Attribut entsprechende Funktion über context
auf. Der this
der Funktion zeigt auf context
🎜🎜call< Die Quelle Die Codesimulation von /code> lautet wie folgt: 🎜rrreee🎜An diesem Punkt haben einige Freunde möglicherweise herausgefunden, dass der in <code>call/apply
übergebene context
kein ist Objekt? 🎜🎜Schauen wir uns zunächst die Beschreibung von mdn
des ersten Parameters der Methode call
an: 🎜🎜Syntax: function.call(thisArg, arg1, arg2 , ..)
thisArg
this
-Wert, der verwendet wird, wenn die Funktion function
ausgeführt wird. Beachten Sie, dass this
möglicherweise nicht der tatsächliche Wert ist, den die Methode sieht: Wenn sich diese Funktion im nicht-strikten Modus befindet, geben Sie null
oder undefiniert</ an. code> wird automatisch ersetzt, um auf das globale Objekt zu verweisen, und der ursprüngliche Wert wird umschlossen</strong><br/>🎜🎜Als nächstes verarbeiten wir den ersten Parameter der Methode <code>myOwnCall
wie folgt : 🎜 rrreee🎜Rufen Sie diese Funktion in der myOwnCall
-Methode auf: 🎜rrreee🎜Die Implementierung von apply
ist im Grunde die gleiche wie call
, außer dass die Der zweite Parameter ist ein Array: 🎜Function.prototype.myOwnBind = function (context, paramsArray) { context = translateToObject(context); const uniqueKey = new Date().getTime(); // this为调用call方法的函数 context[uniqueKey] = this; // 作为对象的方法被对象调用,this指向该对象context const result = context[uniqueKey](...paramsArray); delete context[uniqueKey]; return result; };
相比于call/apply
,bind
函数并没有立即执行函数,而是预先传入函数执行时的this
和参数,并且返回一个函数,在返回的函数中执行调用bind
函数并将预先传入的this
和参数传入
bind
的源码模拟:
Function.prototype.myOwnBind = function (context, ...outerArgs) { const fn = this; return function (...innerArgs) { return fn.call(context, ...outerArgs, ...innerArgs); }; };
精简版如下:
Function.prototype.myOwnBind = (context, ...outerArgs) => (...innerArgs) => this.call(context, ...outerArgs, ...innerArgs);
这里并没有实现通过new
操作符来执行fn.bind(context)
的操作,如果想知道其详细的实现过程,可以看我的这篇文章: JS进阶-手写bind
在深入理解call/apply/bind
的实现原理后,我们尝试完成下面的测试:
function fn1 () {console.log(1);} function fn2 () {console.log(2);} fn1.call(fn2); fn1.call.call(fn2); Function.prototype.call(fn1); Function.prototype.call.call(fn1);
answer:
1. 1 2. 2 3. 什么都不输出 4. 1
这里我们根据call
的源码来进行推导一下Function.prototype.call.call(fn1)
,其它的执行过程类似:
// 1. 首先会将Function.prototype.call作为一个函数来执行它原型上的call方法 // 所以call方法内部: // this => Function.prototype.call // context => fn1 // 通过对象的属性来执行方法改变this指向 // fn1[uniqueKey] = this(Function.prototype.call) // fn1[uniqueKey]() // 执行 Function.prototype.call方法,但是this是context // 2. 在this为fn1的情况下执行Function.prototype.call方法 // 所以call方法内部: // this => fn1 // context => window // 通过对象的属性来改变this指向 // window[uniqueKey] = fn1 // window[uniqueKey]() // 执行fn1(),但是this是window
更多编程相关知识,请访问:编程入门!!
Das obige ist der detaillierte Inhalt vonWohin weist JavaScript?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!