>  기사  >  웹 프론트엔드  >  자바스크립트에서 This 사용법에 대한 예제 튜토리얼

자바스크립트에서 This 사용법에 대한 예제 튜토리얼

零下一度
零下一度원래의
2017-06-25 09:38:121474검색

"당신이 모르는 자바스크립트"라는 책을 여러 번 읽었는데, 읽을 때마다 새로운 발견을 하는 것 같습니다. 내용 중 일부는 한 번에 이해되지 않지만, 몇 가지 개념은 읽을 때마다 이해되는 것 같습니다. 읽어보세요.
this 키워드를 다시 읽어보세요. 개념이 매우 유연하고 이해하기가 매우 어렵기 때문에 자주 읽어도 나쁠 것은 없습니다. 자바스크립트가 전 세계적으로 대중화되어 학습 비용이 저렴해졌으면 좋겠습니다! this关键字。这个概念非常灵活,也非常难掌握,所以我觉得经常读读没有坏处。期待javascript一桶江湖,这样学习的成本就低啦!
参考本书的第二部分的第一章,第二章。

this关键字是js中最最复杂的机制之一。他被自动定义到所有函数的作用域中。

在学习这个关键字的过程中似乎也走了很长时间的弯路。你要问我为什么走了很长时间的弯路,关键的地方还是没有对核心的概念彻底学习和领会,这一点和小学生学习新知识没有任何区别。要想掌握this这个关键字,需要紧扣关键概念,不要凭空想象这到底是怎么一回事。

关键概念:js中的函数在调用的时候,一定,一定,一定会绑定在一个对象上,在分析this关键字的时候,一定要知道函数在调用的时候这个对象到底是谁?。
切记:js中函数的调用和定义是没有任何关系的,函数所绑定的对象直到他被调用的时候才能知道。

this关键字的不确定定是把双刃剑,一是函数调用时的对象不确定性,是js中函数的使用具有很大灵活性,每个对象都可以借用其他函数来完成功能。二是这也造成了this学习的一些困扰。所以在学习的时候先要理解this关键字的优点,然后再去学习造成困扰的地方

首先看看第一段代码
page 75

//注意只是定义了一个函数,并未调用,这时候函数是没有绑定任何对象function identify() {return this.name.toUpperCase();
}//同上面的函数,但是这个函数内部有点复杂,如果下面的代码看不懂//可以只看上面的函数function speak() {var greeting = "Hello, I'm " + identify.call( this );console.log( greeting );
}var me = { //定义了一个字面量对象
    name: "Kyle"
};var you = {//定义了一个字面量对象
    name: "Reader"
};//通过call方式把函数identify分别绑定到两个对象上//这时的this是指向me对象,和you对象
identify.call( me ); // KYLE  
identify.call( you ); // READER//通过call方式把函数call分别绑定到两个对象上//这时的this是指向me对象,和you对象
speak.call( me ); // Hello, I'm KYLE
speak.call( you ); // Hello, I'm READER

在javascript中定义函数的时候,函数是不属于任何对象的。这一点非常的关键,非常的关键,非常的关键。这是理解this关键字的第一个障碍。

this关键字在js函数定义的时候的不确定性使得js函数使用有极大的灵活性,任何对象都可以使用他。

this到底是什么?

this的绑定和函数定义的位置没有任何关系,只取决于函数调用的方式.
javascript中当一个函数被调用的时候,会创建一个活动记录(有时也称上下文)。这个记录包括函数在哪里被调用,函数的调用方法,传入的参数。this就是记录中的一个属性。

这样在学习javascript关键字的首要问题是要解决怎么知道到函数的调用位置.

js对象绑定规则

每个js函数在调用的时候一定要找到一个对象,绑定以后才能使用。 这里是理解了js函数的定义和调用的区别以后需要掌握的一个规模最庞大的概念,在js中一共有四种绑定方式.就我个人来看,绑定规则并不难,难点还是在js的函数作用域的理解. 尤其是默认绑定.这个绑定方式有极大的迷惑性。

默认绑定

这个是函数的独立调用,也就是在一个函数直接调用的时候,似乎是没有绑定到对象上的,但是根据前面的介绍,js中函数调用时必须要绑定到一个对象上。
看下面代码 page 83

  function foo() { //这是函数的定义位置console.log( this.a );
}  var a = 2;//这个变量定义的含义是什么呢?仅仅是赋值给a吗?

  foo(); // 2  //这是函数的调用位置。为什么会打印出2呢?

很多函数都是这么调用的,照猫画虎也可以写出来,但是理解了具体的含义就不一样了。
foo这个函数定义在全局作用域中(window作用域中),巧合的是他的调用也是在全局作用域中,注意这仅仅是巧合,巧合。 那么foo()调用的时候为什么会打印出变量 a的值呢?尽管使用了var这个关键字,但是分析作用域可以知道,a这个变量实际是全局变量,说的再明白一点,a实际是window这个全局对象的一个属性,2是这个属性的属性值。
foo()调用的时候是一丝不挂的全裸状态,仅仅是函数本身,没有任何修饰符,这个时候他也没有任何函数包裹,处在全局作用域下面,所以foo()里面的this是指向全局对象的,当要打印this.a的时候,寻找foo()调用位置会找到全局作用域,找全局作用域的属性this.a的时候会打印出2这个属性值。

我们在使用setTimeout,setInterval函数的时候,实际这两个函数就是一丝不挂的,同样绑定在window对象上。

隐式绑定

函数在调用的时候被添加了修饰符。看下面这个代码
page 85

  function foo() { //定义在全局作用下的函数,仅仅是定义,不是调用位置console.log( this.a );
}var obj = { //定义一个对象
    a: 2,foo: foo
};

obj.foo(); // 2  给foo()函数找了一个对象,this就指向这个对象了

这是最常见的方式了,如果不写前面的obj是不是就是上面的默认绑定了?

隐式丢失이 책의 두 번째 부분 1장과 2장을 참조하세요.

이 키워드는 js에서 가장 복잡한 메커니즘 중 하나입니다. 모든 기능의 범위에서 자동으로 정의됩니다.

저도 이 키워드를 익히는 과정에서 먼 길을 돌아다녔던 것 같습니다. 왜 멀리 돌아왔는지 물어보셔야 합니다. 핵심은 제가 아직 핵심 개념을 완전히 익히지 못하고 이해하지 못했다는 것입니다. 이는 초등학생들이 새로운 지식을 배우는 것과 다르지 않습니다. this 키워드를 마스터하려면 핵심 개념을 고수해야 하며 이것이 무엇인지 상상하지 마세요. 🎜🎜핵심 개념: js에서 함수가 호출되면 반드시 객체에 바인딩됩니다. this 키워드를 분석할 때 함수가 호출될 때 객체가 누구인지 알아야 합니다. . 🎜기억하세요: 호출과 js의 함수 정의 사이에는 관계가 없습니다. 함수에 바인딩된 개체는 호출될 때까지 알 수 없습니다. 🎜🎜이 키워드의 불확실성은 양날의 검입니다. 하나는 함수가 호출될 때 객체의 불확실성입니다. 각 객체는 기능을 완료하기 위해 다른 함수를 빌릴 수 있습니다. 둘째, 이것은 또한 이것을 학습하는 데 몇 가지 문제를 일으켰습니다. 그래서 학습할 때 먼저 이 키워드의 장점을 이해한 다음 문제가 발생하는 곳으로 이동해야 합니다🎜🎜먼저 첫 번째 코드를 살펴보세요🎜75페이지🎜
   var  that=this; //这是什么含义
🎜자바스크립트에서 함수를 정의할 때 함수는 다음과 같습니다. 어떤 객체에도 속하지 않습니다. 이것은 매우 중요합니다. 매우 중요합니다. 매우 중요합니다. 이것이 이 키워드를 이해하는 데 첫 번째 장애물입니다. 🎜
🎜js 함수를 정의할 때 이 키워드의 불확실성으로 인해 js 함수의 사용이 매우 유연해지며 모든 객체에서 이를 사용할 수 있습니다. 🎜

이게 정확히 뭔가요?

🎜이 바인딩은 함수 정의 위치와 아무 관련이 없으며 단지 함수가 호출되는 방식에 따라 다릅니다.🎜JavaScript에서 함수가 호출되면 활동 기록이 생성됩니다(때때로 컨텍스트라고도 함). 이 기록에는 함수가 호출된 위치, 함수 호출 방법, 전달된 매개변수가 포함됩니다. 이는 레코드의 속성입니다. 🎜🎜JavaScript 키워드를 학습할 때 첫 번째 문제는 함수의 호출 위치를 어떻게 알 수 있는지입니다.🎜

js 객체 바인딩 규칙

🎜각 js 함수가 호출되는 위치를 찾아야 합니다. 이때 개체를 사용하고 bind해야 사용할 수 있습니다. js 함수의 정의와 호출의 차이점을 이해한 후 마스터해야 할 가장 큰 개념입니다. js에는 4가지 바인딩 방법이 있습니다. 개인적으로 바인딩 규칙은 어렵지 않습니다. 함수 범위를 이해하는 것이 어렵습니다. 특히 <code>기본 바인딩은 매우 혼란스럽습니다. 🎜

기본 바인딩

🎜이것은 함수의 독립적인 호출입니다. 즉, 함수가 직접 호출되면 객체에 바인딩되지 않는 것 같습니다. 함수는 js에서 호출되며 객체에 바인딩되어야 합니다. 🎜83페이지 아래 코드를 보세요🎜
function foo() { //定义了一个函数console.log( this.a );
}var obj = { //定义了一个对象字面量
    a: 2,foo: foo  //函数作为对对象的属性
};var bar = obj.foo; //把obj对象的函数foo属性赋值给bar变量//这里就是理解这个问题的关键,如果你现在认为调用bar()的时候绑定的对象//是obj那就完全搞错了。这个时候仅仅是把函数foo赋值给了var变量,//并没有把对象也给bar变量,因为这里还不是foo()函数的调用位置,现在//foo函数还没有绑定对象,那么调用bar()的时候对象到底是谁?不知道。//调用的时候才知道。var a = "oops, global"; // 任然是全局对象的属性
bar(); // "oops, global" 这里执行的是默认绑定,this就是去全局对象啦
🎜많은 함수가 이렇게 호출됩니다. 고양이와 호랑이처럼 쓸 수도 있지만 구체적인 의미를 이해하면 다릅니다. 🎜foo 함수는 전역 범위(창 범위)에서 정의됩니다. 공교롭게도 해당 호출도 전역 범위에 있습니다. 그러면 foo()가 호출될 때 변수 a의 값이 출력되는 이유는 무엇입니까? var라는 키워드를 사용했지만, 범위 분석을 통해 변수 a가 실제로 전역 변수임을 알 수 있습니다. 좀 더 명확하게 말하면 a는 실제로 전역 개체 창의 속성이고 2는 이 속성의 속성 값입니다. . 🎜foo()가 호출되면 완전히 노출됩니다. 현재로서는 함수 래퍼가 없고 전역 범위에 있으므로 foo()의 이 항목은 다음을 가리킵니다. 예, this.a를 인쇄하려면 foo()의 호출 위치를 검색하면 전역 범위를 찾을 수 있습니다. 속성 값 2. 🎜
🎜setTimeout 및 setInterval 함수를 사용할 때 이 두 함수는 실제로는 노출되지 않으며 창 개체에도 바인딩됩니다. 🎜

암시적 바인딩

🎜함수 호출 시 수정자가 함수에 추가됩니다. 아래 코드를 보세요🎜85페이지🎜
function foo() { //定义一个函数console.log( this.a );
}function doFoo(fn) { //fn是形参// 如果函数作为实参传入相当于代码 var fn=obj.foo//和上面一段代码是完全一样的,只是函数本身,并没有绑定任何对象

    fn(); // 在这里调用的时候,由于fn只代表foo()函数,被绑定到全局对象上了
}var obj = {a: 2,foo: foo
};var a = "oops, global"; // `a` also property on global object

doFoo( obj.foo ); // "oops, global"不要被obj.foo迷惑了//没有实际执行函数的调用,此时obj.foo仅仅代表没有绑定任何对象的函数//这个代码块看着眼熟么?这就是javascript中回调函数的样子,当//一个函数作为参数传递进另一个函数的时候,这个参数函数就找不到自己绑定的对象是谁了,//所以就默认绑定到全局对象上了。但是我们既然在一个函数里调用另一个函数,肯定是要用这个函数操作当前的对象,那么既然找不到了,我们就手动给他指定一个对象吧。这就是为什么要使用//var  that=this的原因。我觉得理解这个概念,js的功力至少会增加5%
🎜이것이 가장 일반적인 방법입니다. 이전 obj를 작성하지 않으면 위의 기본 바인딩이 될까요? 🎜🎜암묵적 손실🎜js 코드의 중첩된 콜백 함수에서 외부 함수 시작 부분에 문장을 자주 볼 수 있습니다.🎜rrreee🎜이미 사용법을 알고 있을지도 모르지만 더 유용할 것입니다. 그 의미를 이해한다면 매우 편리합니다🎜

看下面段代码.这段代码其实以前我也不太理解,问题还是没有彻底领悟js函数定义和调用之间是没有关系的这一点。
page 86

function foo() { //定义了一个函数console.log( this.a );
}var obj = { //定义了一个对象字面量
    a: 2,foo: foo  //函数作为对对象的属性
};var bar = obj.foo; //把obj对象的函数foo属性赋值给bar变量//这里就是理解这个问题的关键,如果你现在认为调用bar()的时候绑定的对象//是obj那就完全搞错了。这个时候仅仅是把函数foo赋值给了var变量,//并没有把对象也给bar变量,因为这里还不是foo()函数的调用位置,现在//foo函数还没有绑定对象,那么调用bar()的时候对象到底是谁?不知道。//调用的时候才知道。var a = "oops, global"; // 任然是全局对象的属性
bar(); // "oops, global" 这里执行的是默认绑定,this就是去全局对象啦

下面这段代码就是使用var that=this的场景
在使用回调函数的时候要留心。js中函数是一等对象,可以作为另一个函数的参数传入函数。 问题就出在这里了,函数一旦作为实参代替形参的时候,实际也执行了和上面代码一样的赋值过程,实际只是传递了函数本身,原先的对象就没有了。

page 86

function foo() { //定义一个函数console.log( this.a );
}function doFoo(fn) { //fn是形参// 如果函数作为实参传入相当于代码 var fn=obj.foo//和上面一段代码是完全一样的,只是函数本身,并没有绑定任何对象

    fn(); // 在这里调用的时候,由于fn只代表foo()函数,被绑定到全局对象上了
}var obj = {a: 2,foo: foo
};var a = "oops, global"; // `a` also property on global object

doFoo( obj.foo ); // "oops, global"不要被obj.foo迷惑了//没有实际执行函数的调用,此时obj.foo仅仅代表没有绑定任何对象的函数//这个代码块看着眼熟么?这就是javascript中回调函数的样子,当//一个函数作为参数传递进另一个函数的时候,这个参数函数就找不到自己绑定的对象是谁了,//所以就默认绑定到全局对象上了。但是我们既然在一个函数里调用另一个函数,肯定是要用这个函数操作当前的对象,那么既然找不到了,我们就手动给他指定一个对象吧。这就是为什么要使用//var  that=this的原因。我觉得理解这个概念,js的功力至少会增加5%

위 내용은 자바스크립트에서 This 사용법에 대한 예제 튜토리얼의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.