>  기사  >  웹 프론트엔드  >  이 포인터에 대한 자세한 설명을 통해 이를 이해하고 전화하고 적용할 수 있는 기사를 하나의 문서로 제공합니다.

이 포인터에 대한 자세한 설명을 통해 이를 이해하고 전화하고 적용할 수 있는 기사를 하나의 문서로 제공합니다.

coldplay.xixi
coldplay.xixi앞으로
2021-03-16 09:56:112498검색

이 포인터에 대한 자세한 설명을 통해 이를 이해하고 전화하고 적용할 수 있는 기사를 하나의 문서로 제공합니다.

목차

  • 머리말 + 질문
  • 1. 통화 및 적용
  • 3. 통화 시뮬레이션
  • 5.
  • 머리말 + 생각하는 질문

인턴십을 찾을 때 항상 JS에 익숙한 이력서에 this, call, Apply 등의 문장을 추가했던 기억이 나네요...

(무료 학습 추천: 이 포인터에 대한 자세한 설명을 통해 이를 이해하고 전화하고 적용할 수 있는 기사를 하나의 문서로 제공합니다.

javascript 비디오 튜토리얼)저는 이력서를 제출할 때마다 다음 단계를 거치게 됩니다

면접 전에 Du Niang에게 물어보세요 - 어떤 유형인지 포인팅은 ~, 호출, 적용으로 구분할 수 있는데 차이점이 무엇인가요? 자신감이 0%에서 50%로 치솟았네요

면접때 면접관이 몇문제를 닥치는 대로 던지는데, 확고한 답변을 해줄 수 있는데 결과는 늘 불만족스럽네요...
  • 면접이 끝난 후, 부끄럽습니다. 이력서에서 이 항목을 삭제하세요. 그리고 나중에 이력서 제출할 때 이 항목을 또 추가했는데...
생각하는 질문

이 포인터에 대한 자세한 설명을 통해 이를 이해하고 전화하고 적용할 수 있는 기사를 하나의 문서로 제공합니다.다음 질문은 제가 인터넷에서 검색한 인기 질문들입니다. 전문가들이 쉽게 답변해 주신다면. 명확한 아이디어라면 엄지손가락을 치켜세우는 것이 좋을 것입니다(결국 뇌 세포를 많이 소모하기 때문입니다). 댓글로 몇 가지 조언을 해주시면 더 좋을 것 같습니다! ! !

빈칸 채우기:

Javascript에서 [ ] 함수를 실행하면 새 함수가 호출된 함수와 동일한 함수 본문을 갖습니다. 호출되면 이 값은 첫 번째 매개변수를 가리킵니다.

  • Q&A: 【 】函数会创建一个新函数,新函数与被调函数具有相同的函数体,当目标函数被调用时 this 值指向第一个参数。

问答题:

  • 请你谈一下改变函数内部this指针的指向函数有哪几种,他们的区别是什么?
  • this的指向可以分为哪几种?

代码分析题:

var name = 'window'var person1 = {
  name: 'person1',
  show1: function () {
    console.log(this.name)
  },
  show2: () => console.log(this.name),
  show3: function () {
    return function () {
      console.log(this.name)
    }
  },
  show4: function () {
    return () => console.log(this.name)
  }}var person2 = { name: 'person2' }person1.show1()person1.show1.call(person2)person1.show2()person1.show2.call(person2)person1.show3()()person1.show3().call(person2)person1.show3.call(person2)()person1.show4()()person1.show4().call(person2)person1.show4.call(person2)()

一、this的指向

百度、谷歌上输入“this的指向”关键字,大几千条文章肯定是有的,总不至于为了全方面、无死角的掌握它就要将所有的文章都看一遍吧?所以不如梳理出一个稳固的框架,顺着我们的思路来填充它。

思维导图

이 포인터에 대한 자세한 설명을 통해 이를 이해하고 전화하고 적용할 수 있는 기사를 하나의 문서로 제공합니다.

本节精华:

  • this 总是(非严格模式下)指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境;
  • 除了不常用的with和eval的情况,具体到实际应用中,this指向大概可以分为四种:
    • 作为对象的方法调用;
    • 作为普通函数调用;
    • 构造器调用;
    • call 或 apply调用;
    • 箭头函数中,this指向函数上层作用域的this;
  • 构造器普通函数的区别在于被调用的方式
  • A,call(B) => 可以理解成在B的作用域内调用了A方法;

分析

1、作为对象的方法调用

当函数作为对象的方法被调用时,this指向该对象

var obj = {
    a: 'yuguang',
    getName: function(){
        console.log(this === obj);
        console.log(this.a);
    }};obj.getName(); // true yuguang

2、作为普通函数调用

当函数不作为对象的属性被调用,而是以普通函数的方式,this总是指向全局对象(在浏览器中,通常是Window对象)

window.name = 'yuguang';var getName = function(){
    console.log(this.name);};getName(); // yuguang

或者下面这段迷惑性的代码:

window.name = '老王'var obj = {
    name: 'yuguang',
    getName: function(){
        console.log(this.name);
    }};var getNew = obj.getName;getNew(); // 老王

而在ES5的严格模式下,this被规定为不会指向全局对象,而是undefined

3、构造器调用

除了一些内置函数,大部分Js中的函数都可以成为构造器,它们与普通函数没什么不同

构造器普通函数的区别在于被调用的方式

함수 내에서 this 포인터를 변경하는 포인터 함수의 종류와 차이점에 대해 이야기해주세요.

이것은 어떤 방향으로 나눌 수 있나요?

코드 분석 질문:

var MyClass = function(){
    this.name = 'yuguang';}var obj = new MyClass();obj.name; // yuguang

1. 요점은

바이두와 구글에 "point of this"라는 키워드를 입력하세요. 수천 개의 기사가 있을 텐데 모든 것을 포함하지는 않습니다. , 사각지대 없이 마스터하려면 기사를 다 읽어야겠죠? 그러니 탄탄한 틀을 정리하고 우리의 생각대로 채워가는 것이 좋습니다.

마인드맵🎜🎜여기에 그림 설명 삽입🎜 🎜The 이 섹션의 핵심: 🎜🎜🎜이것은 항상 객체(비엄격 모드)를 가리키며, 가리키는 특정 객체는 함수가 아닌 런타임 시 함수의 실행 환경을 기반으로 동적으로 바인딩됩니다. 선언된 환경 🎜🎜일반적이지 않은 with 및 eval 상황을 제외하고 실제 응용 프로그램에서 이 포인터는 대략 4가지 유형으로 나눌 수 있습니다. 🎜🎜객체의 메서드 호출 🎜🎜일반적인 함수 호출; 🎜🎜 생성자 호출; 🎜🎜호출 또는 적용 🎜🎜화살표 함수에서 이는 함수의 상위 범위를 가리킵니다. 🎜🎜🎜🎜🎜constructor🎜와 🎜일반 함수🎜의 차이점은 다음과 같습니다. 가 호출됩니다;🎜🎜A,call(B) => B의 범위 내에서 메소드 A가 호출되는 것으로 이해할 수 있습니다.🎜🎜🎜Analytic🎜🎜🎜1. 🎜🎜함수가 객체일 때 메소드가 호출될 때 <code>이것은 객체를 가리킨다🎜
var MyClass = function () {
    this.name = 1;
    return {
        name: 2
    }}var myClass = new MyClass(); console.log('myClass:', myClass); // { name: 2}
🎜🎜2. 일반 함수로 호출됩니다🎜🎜🎜함수가 의 속성으로 호출되지 않을 때 객체이지만 일반 함수에서는 항상 전역 객체(브라우저에서는 일반적으로 Window 객체)를 가리킵니다. 🎜
var obj1 = {
    name: 1,
    getName: function (num = '') {
        return this.name + num;
    }};var obj2 = {
    name: 2,};// 可以理解成在 obj2的作用域下调用了 obj1.getName()函数console.log(obj1.getName()); // 1console.log(obj1.getName.call(obj2, 2)); // 2 + 2 = 4console.log(obj1.getName.apply(obj2, [2])); // 2 + 2 = 4
🎜 또는 다음과 같은 혼란스러운 코드: 🎜
this.val = 2;var obj = {
    val: 1,
    getVal: () => {
        console.log(this.val);
    }}obj.getVal(); // 2
🎜 ES5의 엄격 모드에서는 그렇지 않다고 규정되어 있습니다. 전역 객체를 가리키지만 undefine🎜🎜🎜3. 생성자 호출🎜🎜🎜일부 내장 함수를 제외하면 Js의 대부분 함수는 생성자가 될 수 있습니다. 🎜🎜🎜constructors🎜and🎜ordinary 함수 🎜의 차이점은 호출 방식에 있습니다. 🎜 new 연산자가 함수를 호출하면 항상 개체를 반환하며 이는 일반적으로 이 개체를 가리킵니다 🎜
var obj = {
    name: '1',
    getName: function (params) {
        console.log(this.name)
    }};obj.getName();var getName2 = obj.getName;getName2();
🎜 그러나 함수가 명시적으로 객체 객체를 반환하는 경우 이 작업의 결과는 결국 이 객체를 반환하게 됩니다. 🎜
var getDomById = function (id) {
    return document.getElementById(id);};getDomById('p1') //dom节点
🎜생성자가 명시적으로 데이터를 반환하지 않거나 객체 유형이 아닌 데이터를 반환하는 한 위의 문제는 발생하지 않습니다. 🎜🎜🎜4. 호출 또는 적용 호출🎜🎜🎜일반 함수 호출과 비교하여 호출 및 적용은 함수의 this를 동적으로 변경할 수 있습니다🎜
var getDomById = document.getElementByIdgetDomById('p1') // Uncaught TypeError: Illegal invocation(非法调用)
🎜🎜5. 화살표 함수는 자체 this를 생성하지 않습니다. 자체 범위 체인의 상위 수준에서만 이를 상속합니다. 🎜

因此,在下面的代码中,传递给setInterval的函数内的this与封闭函数中的this值相同:

this.val = 2;var obj = {
    val: 1,
    getVal: () => {
        console.log(this.val);
    }}obj.getVal(); // 2

常见的坑

就像标题一样,有的时候this会指向undefined

情况一

var obj = {
    name: '1',
    getName: function (params) {
        console.log(this.name)
    }};obj.getName();var getName2 = obj.getName;getName2();

这个时候,getName2()作为普通函数被调用时,this指向全局对象——window。

情况二

当我们希望自己封装Dom方法,来精简代码时:

var getDomById = function (id) {
    return document.getElementById(id);};getDomById('p1') //dom节点

那么我们看看这么写行不行?

var getDomById = document.getElementByIdgetDomById('p1') // Uncaught TypeError: Illegal invocation(非法调用)

这是因为:

  • 当我们去调用document对象的方法时,方法内的this指向document
  • 当我们用getId应用document内的方法,再以普通函数的方式调用,函数内容的this就指向了全局对象。

利用call和apply修正情况二

document.getElementById = (function (func) {
    return function(){
        return func.call(document, ...arguments)
    }})(document.getElementById) // 利用立即执行函数将document保存在作用域中

이 포인터에 대한 자세한 설명을 통해 이를 이해하고 전화하고 적용할 수 있는 기사를 하나의 문서로 제공합니다.

二、call和apply

不要因为它的“强大”而对它产生抗拒,了解并熟悉它是我们必须要做的,共勉!

思维导图

이 포인터에 대한 자세한 설명을 통해 이를 이해하고 전화하고 적용할 수 있는 기사를 하나의 문서로 제공합니다.

1.call和apply区别

先来看区别,是因为它们几乎没有区别,下文代码实例call和apply都可以轻易的切换。

当它们被设计出来时要做到的事情一摸一样,唯一的区别就在于传参的格式不一样

  • apply接受两个参数
    • 第一个参数指定了函数体内this对象的指向
    • 第二个参数为一个带下标的参数集合(可以是数组或者类数组)
  • call接受的参数不固定
    • 第一个参数指定了函数体内this对象的指向
    • 第二个参数及以后为函数调用的参数

因为在所有(非箭头)函数中都可以通过arguments对象在函数中引用函数的参数。此对象包含传递给函数的每个参数,它本身就是一个类数组,我们apply在实际使用中更常见一些。

call是包装在apply上面的语法糖,如果我们明确的知道参数数量,并且希望展示它们,可以使用call。

当使用call或者apply的时候,如果我们传入的第一个参数为null,函数体内的this会默认指向宿主对象,在浏览器中则是window

借用其他对象的方法

我们可以直接传null来代替任意对象

Math.max.apply(null, [1, 2, 3, 4, 5])

2.call和apply能做什么?

使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数——来时MDN

  • 调用构造函数来实现继承;
  • 调用函数并且指定上下文的 this;
  • 调用函数并且不指定第一个参数;

1.调用构造函数来实现继承

通过“借用”的方式来达到继承的效果:

function Product(name, price) {
	this.name = name;
	this.price = price;}function Food(name, price) {
	Product.call(this, name, price); //
	this.category = food;}var hotDog = new Food('hotDog', 20);

2.调用函数并且指定上下文的 this

此时this被指向了obj

function showName() {
    console.log(this.id + ':' + this.name);};var obj = {
    id: 1,
    name: 'yuguang'};showName.call(obj)

3.使用call单纯的调用某个函数

Math.max.apply(null, [1,2,3,10,4,5]); // 10

이 포인터에 대한 자세한 설명을 통해 이를 이해하고 전화하고 적용할 수 있는 기사를 하나의 문서로 제공합니다.

三、模拟实现一个call

先来看一下call帮我们需要做什么?

var foo = {
	value: 1};function show() {
	console.log(this.value);};show.call(foo); //1

就像解方程,要在已知条件中寻找突破哦口:

  • call 使得this的指向变了,指向了foo;
  • show 函数被执行了;
  • 传入的参数应为 this + 参数列表;

第一版代码

上面提到的3点,仅仅完成了一点,且传入的参数

var foo = {
    value: 1};function show() {
    console.log(this.value);};Function.prototype.setCall = function (obj) {
    console.log(this); // 此时this指向show
    obj.func = this; // 将函数变成对象的内部属性
    obj.func(obj.value); // 指定函数
    delete obj.func // 删除函数,当做什么都没发生~}show.setCall(foo);

第二版代码

为了解决参数的问题,我们要能获取到参数,并且正确的传入:

var foo = {
    value: 1};function show(a, b) {
    console.log(this.value);
    console.log(a + b);};Function.prototype.setCall = function (obj) {
    obj.fn = this; // 将函数变成对象的内部属性
    var args = [];
    for(let i = 1; i <p>此时,我们就可以做到,传入多个参数的情况下使用call了,但是如果你仅想用某个方法呢?</p><p><strong>第三版代码</strong></p><pre class="brush:php;toolbar:false">Function.prototype.setCall = function (obj) {
    var obj = obj || window;
    obj.fn = this;
    var args = [];
    for(var i = 1, len = arguments.length; i <p><strong>四、bind</strong></p><blockquote><p>bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用 —— MDN</p></blockquote><p>提到了<strong>call</strong>和<strong>apply</strong>,就绕不开<strong>bind</strong>。我们试着来模拟一个bind方法,以便加深我们的认识:</p><pre class="brush:php;toolbar:false">Function.prototype.bind = function (obj) {
    var _this = this; // 保存调用bind的函数
    var obj = obj || window; // 确定被指向的this,如果obj为空,执行作用域的this就需要顶上喽
    return function(){
        return _this.apply(obj, arguments); // 修正this的指向
    }};var obj = {
    name: 1,
    getName: function(){
        console.log(this.name)
    }};var func = function(){
    console.log(this.name);}.bind(obj);func(); // 1

这样看上去,返回一个原函数的拷贝,并拥有指定的 this 值,还是挺靠谱的哦~

写在最后

JavaScript 내부 기술의 기본 부분 중 첫 번째 부분입니다. 요약하면 이 시리즈는 Xian Yu에게 큰 격려와 영감을 얻었습니다. 이 시리즈에는 약 15개의 기사가 있으며, 모두 우리가 가장 자주 인터뷰하지만 직장에서는 종종 무시됩니다. .

관련 무료 학습 권장사항: javascript(동영상)

위 내용은 이 포인터에 대한 자세한 설명을 통해 이를 이해하고 전화하고 적용할 수 있는 기사를 하나의 문서로 제공합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제