JavaScript はどこを指しているのでしょうか?

青灯夜游
リリース: 2021-06-15 16:27:35
オリジナル
3815 人が閲覧しました

これは以下を指します: 1. 通常の関数またはオブジェクト属性として、ウィンドウ オブジェクトを指します; 2. イベント バインディング内で、バインドされたイベントの要素を指します; 3. コンストラクター内で、クラスのインスタンス; 4. 矢印 関数では、最も近い親コンテキストで this を指します; 5. call/apply/bind では、渡された最初のパラメーターを指します。

JavaScript はどこを指しているのでしょうか?

このチュートリアルの動作環境: Windows7 システム、JavaScript バージョン 1.8.5、Dell G3 コンピューター

JavaScriptthis次の状況を指します:

  • 通常の関数またはオブジェクト属性として
  • イベント バインディング
  • コンストラクター
  • Arrow function
  • call/apply/bindSpecify

一つずつ紹介しましょう

通常の関数またはオブジェクト属性として

this は、メソッドの実行前に「ドット」があるかどうかによって決まります。「ドット」がある場合は、その「ドット」の前にいる人が決まります。 this になります。ドットがない場合、thiswindow

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 は関数を呼び出したオブジェクトを指します。それ以外の場合、その thiswindow を指します。

イベント バインディング

イベント バインディングを実行する場合、イベント バインディング関数の

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
ログイン後にコピー

しかし、注意する必要があります。ここでは、ユーザーがクリックすると、ブラウザーがクリック イベントの

thisDOM# にポイントするのに役立ちます。 ## イベントにバインドされた要素。対応するイベントがコードを通じてトリガーされる場合は、call/apply/bind( new Fn#) を通じてその this

$button.click.call() // this为window,打印结果为100
ログイン後にコピー

コンストラクターを指定できます。 ##)コンストラクター (new Fn

) が実行されます。関数内の

this は、現在のクラス ( です) のインスタンスです。 new キーワードは、これを行うのに役立ちます:

var x = 100;
const Fn = function () {
  this.x = 200;
  console.log(this.x);
};

const fn = new Fn();
ログイン後にコピー
answer:
1. 200
ログイン後にコピー

arrow function

矢印には独自の ## がありません関数 #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 実行時のパラメータで構成される配列です。配列内の各項目は、fnbind ## の各パラメータに対応します。 #実行時、最初のパラメータは事前​​に this に渡されたポインタ、以降のパラメータは実際に
  • fn
  • を呼び出す前に渡されたパラメータで、戻り値はfunctionfixedThisFnfixedThisFn は内部で fn を呼び出し、その this を指すように指定します。より深い理解call/apply/bind は、関数内で this
  • が指すものをどのように変更しますか? 以下では、これら 3 つの関数をシミュレートして実装します

call/apply/bindソース コードの実装

前の紹介によると、関数がオブジェクト プロパティとして呼び出されるとき、this は関数を呼び出すオブジェクト
const obj = { x: 100, fn () {console.log(this);} };
obj.fn(); // {x: 100, fn: function() {...}} => obj
ログイン後にコピー

JavaScript

のこの機能を使用すると、実行された関数を call/ の最初のパラメーター context

の属性として使用できます。 apply

を実行し、context を渡します。この属性に対応する関数を呼び出すには、関数の thiscontext## を指します。 #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;
};
ログイン後にコピー
この時点で、context

call/ に渡されたらどうなるかに気付いた友人もいるかもしれません。 apply はオブジェクトではありませんか?

まず、

mdn による call メソッドの最初のパラメーターの説明を見てみましょう:

構文:

function.call( thisArg 、 arg1、 arg2、 ...) * thisArg

オプション。
function 関数の実行時に使用される this
値。 this は、このメソッドで表示される実際の値ではない可能性があることに注意してください。この関数が非厳密モードの場合、
の場合は、null または unknown になります。指定すると、グローバル オブジェクトを指すように自動的に置き換えられ、元の値がラップされます。 次に、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# と同じです。 ## (2 番目を除く) パラメーターは配列です: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">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; };</pre><div class="contentsignin">ログイン後にコピー</div></div><p>相比于<code>call/applybind函数并没有立即执行函数,而是预先传入函数执行时的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
ログイン後にコピー

更多编程相关知识,请访问:编程入门!!

以上がJavaScript はどこを指しているのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート