JavaScript のこのオブジェクト

Jul 07, 2018 am 11:06 AM

この記事では、特定の参照値を持つ Javascript の this オブジェクトを主に紹介します。必要な友人はそれを参照できます。

this の使用に関して、私たちが最も頻繁に遭遇するのは次のとおりです。全体的な状況 関数内、オブジェクト メソッド内、呼び出しと適用、クロージャ内、アロー関数内、クラス内

このオブジェクトは、関数を呼び出す前に、関数の実行環境に基づいてバインドされていることがわかります。値は固定されていないため、コードの実行中に別のオブジェクトを参照します。どのオブジェクト インスタンスが this が配置されている関数を呼び出すか、これはどのオブジェクト インスタンスを表します。

1. グローバル関数

グローバル関数では、これは window に相当します。ここで、関数 person() はグローバル環境で実行されるため、グローバル スコープ person() は window オブジェクトによって呼び出されるため、この時点では window オブジェクトを指します。この関数がオブジェクト o に割り当てられ、o.sayName() が呼び出される場合、これはオブジェクト o を参照するため、this.name の評価は o.name の評価になります。

var name = "Tina";function sayName() {
    alert(this.name);
}
person();//Tina
ログイン後にコピー

2. オブジェクトのメソッド

関数がオブジェクトのメソッドとして呼び出される場合、これはそのオブジェクトと等価です。 3. call( )、apply()、bind()

call(ctx, parm1,parm2,parm3...) と apply(ctx,[parms]) の目的は、特定のスコープの関数は、実際には関数本体でこのオブジェクトの値を設定することと同じです。

 name = "Tina"
ログイン後にコピー

上記の例では、callSum1() と callSum2() は、関数 sum( を実行するときに this の値として this を渡します) ) (グローバル スコープで呼び出されるため、ウィンドウ オブジェクトが渡されます); 実際、call と apply の最も強力な点は、関数が実行されるスコープを拡張できることです。例:

var name="Tina";var obj={
      name="Tony",
      getName: function() {
            alert(this.name);
      }
};
obj.getName();//"Tony"
ログイン後にコピー

binding() メソッドは関数のインスタンスを作成し、その this 値は、bind() 関数に渡される値にバインドされます。例:

function sum(num1, num2)  {      return num1+num2;
}function callSum1(num1, num2) {      return sum.apply(this, [num1, num2]);
}function callSum2(num1,num2) {      return sum.call(this, num1, num2);
}
alert(callSum1(10, 10)); //20alert(callSum2(10, 10));//20
ログイン後にコピー

別の使用シナリオは関数バインディングです。関数バインディングは、特定の環境で指定されたパラメーターで別の関数を呼び出すことができる関数を作成することです。この手法はコールバック関数やイベント処理でよく使用されます。関数を変数として渡しながらコードの実行環境を保持するプログラムと組み合わせて使用​​します。

window.color="red";var o={ color: "blue"};function sayColor() {
      alert(this.color);
}
sayColor();//"red"sayColor.call(this);//"red"sayColor.call(window);//"red"sayColor.call(o);//"blue"
ログイン後にコピー

ボタンを押すと関数が呼び出され、警告ボックスが表示されるように見えますが、実際には未定義と表示されます。その理由は、handler.handleClick() の実行環境が保存されていないため、このオブジェクトは最終的にハンドラーではなく DOM ボタンを指すことになります (IE8 では、これはウィンドウを指します)。この問題を解決する 1 つの方法は、クロージャーを使用することです。もちろん、これはこのコードに固有のソリューションです。複数のクロージャを作成すると、コードの理解やデバッグが困難になる可能性があることがわかっています。したがって、多くの JS ライブラリは、関数を指定された環境にバインドできる関数を実装しています。この関数は通常、bind() と呼ばれ、ECMAScript 5 ではすべての関数に対してネイティブの binding() メソッドが定義されており、その使用法は次のとおりです。

window.color="red";var o={ color: "blue" };function sayColor() {
    alert(this.color);
}var objsayColor = sayColor.bind(o);
objsayColor();//"blue"
ログイン後にコピー

単純なbind()関数はパラメータと環境を受け入れ、指定された環境で指定された関数を呼び出す関数を返し、すべてのパラメータを変更せずに渡します。構文は次のとおりです:

var handler = {
      message: "Event handled",
      handleClick : function(event) {
            alert(this.message);
      }
};var btn = document.getElementById("my_btn");
btn.addEventListener("click", handler.handleClick, false);
ログイン後にコピー

この関数は、bind() でクロージャを作成し、渡された関数を呼び出すために apply を使用し、適用するコンテキスト オブジェクトと引数オブジェクトの配列を渡します。内部関数 (匿名関数)。bind() のパラメータではありません。返された関数が呼び出されると、指定された環境で渡された関数が実行され、すべての引数が与えられます。

ネイティブの binding() メソッドは、以前にカスタマイズされた binding() メソッドに似ており、どちらもこの値としてオブジェクトを渡す必要があります。これらは主にイベント ハンドラーと setTimeout() および setInterval() で使用されます。バインディングは、反応イベント処理でこれをバインドする際のアロー関数と同じ役割を果たすことがよくあります。

4. クロージャ

クロージャの書き方が異なるため、このオブジェクトをクロージャで使用すると問題が発生する場合があります

由于getNameFunc()返回一个函数,因此调用object.getNameFunc()()就会立即调用它返回的函数,结果就是返回一个字符串"The window",即全局变量的值,此时匿名函数没有取得其包含作用域(外部作用域)的this对象。原因在于内部函数在搜索两个特殊变量this和arguments时,只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量。这时,只需把把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象了。

var name = "The window";var object = {
      name: "My Object",
      getNameFunc: function() {            
      var that = this;            
      return function() {                  
      return that.name;
            };
      }
};
alert(object.getNameFunc()());//"My Object"
ログイン後にコピー

//节流function throttle(fn, delay) {      
var previous = Data.now();      
return function() {             
var ctx = this;             
var args = arguments;             
var now = Data.now();             
var diff = now-previous-delay;              
if(diff>=0) {
                    previous = now;
                    setTimeout(function() {
                         fn.apply(ctx, args);
                    }, delay);
              }
       };
}
ログイン後にコピー

5. 箭头函数

我们知道,箭头函数有几个需要注意的点:

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象;

(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误;

(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替;

(4)不可以使用yield命令,因此箭头函数不能用作Generator函数;

这里我们只谈论第一点;this对象的指向是可变的,但在箭头函数中,它是固定的;

function foo() {
      setTimeout(() => {
          console.log('id: ', this.id);
      }, 100);
}var id=21;
foo.call({id: 31});//id: 31
ログイン後にコピー

上述代码中,setTimeout是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它真正加入到执行栈后还要等到100毫秒后才会执行,如果是普通函数,此时的this应该指向全局对象window,这时应该输出21。但是,箭头函数导致this总是指向函数定义生效时所在的对象(本例是{id:31})所以输出的是id: 31;

箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。下面是另一个例子:

function Timer() {      this.s1 = 0;      this.s2 = 0;
      setInterval(() => this.s1++, 1000);
      setInterval(function() {            this.s2++;
      }, 1000);
}var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3100);//s1: 3setTimeout(() => console.log('s2: ', timer.s2), 3100);//s2: 0
ログイン後にコピー

上面代码中,Timer函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的this绑定定义时所在的作用域(Timer函数),后者的this指向运行时所在的作用域(即全局对象)。所以,3100毫秒后,timer.s1被更新了3次,timer.s2一次都没更新。

箭头函数可以让this指向固定化,这种特性很有利于封装回调函数。下面代码将DOM事件的回调函数封装在一个对象里面。

var handler = {
      id: '123456',
      init: function() {
            document.addEventListener('click',
                event => this.doSomething(event.type), false);
      },
      doSomething: funcition(type) {
            console.log('Handling ' + type + ' for ' + this.id);
      }
};
ログイン後にコピー

上面代码的init方法中,使用了箭头函数,这导致这个箭头函数里面的this,总是指向handler对象。否则,回调函数运行时,this.doSomething这一行会报错,因为此时this指向document对象。this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码的this。正是因为它没有this,所以也就不能用作构造函数。由于箭头函数没有自己的this,所以当然不能用call()、apply()、bind()改变this的指向。

6. class

类的方法内部如果含有this,它默认指向类的实例。

class Logger {    /*constructor() {
        this.printName = this.printName.bind(this);
    }*/
    printName(name = 'Nicolas') {        this.print(`Hello ${name}`);
    }
    print(text) {
        console.log(text);
    }
}
const logger = new Logger();
const { printName } = logger;
printName();
ログイン後にコピー

上面代码中,printName方法中的this,默认指向Logger类的实例。但是,如果将这个方法提取出来单独使用,this会指向该方法运行时所在的环境,因为找不到print方法而导致报错。一种简单的解决方法就是在构造函数中绑定this。而另一种方法是使用箭头函数:

class Logger {
    constructor() {        this.printName = (name='Nicolas') => {            this.print(`Hello ${name}`);
    }
    print(text) {
        console.log(text);
    }
}
const logger = new Logger();
const { printName } = logger;
printName();
ログイン後にコピー

还有一种方法是使用Proxy,获取方法的时候,自动绑定this。

function selfish (target) {
  const cache = new WeakMap();
  const handler = {
    get (target, key) {
      const value = Reflect.get(target, key);      if (typeof value !== 'function') {        return value;
      }      if (!cache.has(value)) {
        cache.set(value, value.bind(target));
      }      return cache.get(value);
    }
  };
  const proxy = new Proxy(target, handler);  return proxy;
}
const logger = selfish(new Logger());
ログイン後にコピー

 以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

foreach, for in, for of 之间的异同

Vue+Electron实现简单桌面应用

JS定时器和单线程异步特性

以上がJavaScript のこのオブジェクトの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? Apr 04, 2025 pm 02:42 PM

フロントエンドのサーマルペーパーチケット印刷のためのよくある質問とソリューションフロントエンド開発におけるチケット印刷は、一般的な要件です。しかし、多くの開発者が実装しています...

誰がより多くのPythonまたはJavaScriptを支払われますか? 誰がより多くのPythonまたはJavaScriptを支払われますか? Apr 04, 2025 am 12:09 AM

スキルや業界のニーズに応じて、PythonおよびJavaScript開発者には絶対的な給与はありません。 1. Pythonは、データサイエンスと機械学習でさらに支払われる場合があります。 2。JavaScriptは、フロントエンドとフルスタックの開発に大きな需要があり、その給与もかなりです。 3。影響要因には、経験、地理的位置、会社の規模、特定のスキルが含まれます。

javascriptの分解:それが何をするのか、なぜそれが重要なのか javascriptの分解:それが何をするのか、なぜそれが重要なのか Apr 09, 2025 am 12:07 AM

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

JavaScriptを使用して、同じIDを持つArray要素を1つのオブジェクトにマージする方法は? JavaScriptを使用して、同じIDを持つArray要素を1つのオブジェクトにマージする方法は? Apr 04, 2025 pm 05:09 PM

同じIDを持つ配列要素をJavaScriptの1つのオブジェクトにマージする方法は?データを処理するとき、私たちはしばしば同じIDを持つ必要性に遭遇します...

Shiseidoの公式Webサイトのように、視差スクロールと要素のアニメーション効果を実現する方法は?
または:
Shiseidoの公式Webサイトのようにスクロールするページを伴うアニメーション効果をどのように実現できますか? Shiseidoの公式Webサイトのように、視差スクロールと要素のアニメーション効果を実現する方法は? または: Shiseidoの公式Webサイトのようにスクロールするページを伴うアニメーション効果をどのように実現できますか? Apr 04, 2025 pm 05:36 PM

この記事の視差スクロールと要素のアニメーション効果の実現に関する議論では、Shiseidoの公式ウェブサイト(https://www.shisido.co.co.jp/sb/wonderland/)と同様の達成方法について説明します。

JavaScriptは学ぶのが難しいですか? JavaScriptは学ぶのが難しいですか? Apr 03, 2025 am 12:20 AM

JavaScriptを学ぶことは難しくありませんが、挑戦的です。 1)変数、データ型、関数などの基本概念を理解します。2)非同期プログラミングをマスターし、イベントループを通じて実装します。 3)DOM操作を使用し、非同期リクエストを処理することを約束します。 4)一般的な間違いを避け、デバッグテクニックを使用します。 5)パフォーマンスを最適化し、ベストプラクティスに従ってください。

フロントエンド開発でVSCodeと同様に、パネルドラッグアンドドロップ調整機能を実装する方法は? フロントエンド開発でVSCodeと同様に、パネルドラッグアンドドロップ調整機能を実装する方法は? Apr 04, 2025 pm 02:06 PM

フロントエンドのVSCodeと同様に、パネルドラッグアンドドロップ調整機能の実装を調べます。フロントエンド開発では、VSCODEと同様のVSCODEを実装する方法...

Console.log出力の違い結果:なぜ2つの呼び出しが異なるのですか? Console.log出力の違い結果:なぜ2つの呼び出しが異なるのですか? Apr 04, 2025 pm 05:12 PM

Console.log出力の違いの根本原因に関する詳細な議論。この記事では、Console.log関数の出力結果の違いをコードの一部で分析し、その背後にある理由を説明します。 �...

See all articles