首页 > 其他分享 >谈谈你对this的理解?

谈谈你对this的理解?

时间:2022-08-22 21:11:34浏览次数:346  
标签:function console log 指向 谈谈 理解 var obj

目录

谈谈你对this的理解?

this指向问题

this,指向的是函数调用者,不同情况下它的指向不同。

  1. 函数调用模式 fn() 指向window的情况 ( 默认绑定)
  2. 方法调用模式 obj.fn() 谁调用, this指向谁,( 隐式绑定)
  3. 上下文调用模式 , 想让this指向谁, this就指向谁, (显式绑定,又叫做硬绑定 call()、 apply() 、 bind())
function Person(userName) {
  this.userName = userName;   //构造函数中的this指向实例对象person
}
var person = new Person("lisi");
console.log(person.userName);     //lisi
var a = 10;
   var obj = {
     a: 120,
     method: function () {
       var bar = function () {
         console.log(this.a);          //10 window调用
       };
       bar();
       return this.a;
     },
   };
   console.log(obj.method()); // 120  对象调用
var num = 10;
   function Person() {
     num = 20;
     this.num = 30;
   }
   Person.prototype.getNum = function () {
     return this.num;
   };
   var person = new Person();
   console.log(person.getNum());      //30 对象调用

var fullName = "language";
   var obj = {
     fullName: "javascript",
     prop: {
       getFullName: function () {
         return this.fullName;
       },
     },
   };
   console.log(obj.prop.getFullName()); // undefined  obj.prop调用
   var test = obj.prop.getFullName; // language
   console.log(test());//window调用
var val = 1;
   var json = {
     val: 10,
     dbl: function () {
       //val *= 2;       1*2=2
       this.val *= 2;     //10*2=20
     },
   };
   json.dbl();
   //console.log(json.val + val)       10+2=12
   console.log(json.val + val)         //21
     var num = 10;
      var obj = { num: 20 };
      obj.fn = (function (num) {
        this.num = num * 3; // this.num = 60  //this window
        num++; // 21
        return function (n) {
          this.num += n; // 65  30 //this obj
          num++; // 22  23
          console.log(num); // 22 23
        };
      })(obj.num);
      var fn = obj.fn;
      fn(5);
      obj.fn(10);
      console.log(num, obj.num); // 65 30
var value = 10;
   var obj = {
     value: 20,
   };
   var method = function () {
     console.log(this.value);
   };
   method(); // 10
   method.call(obj); // 20
   method.apply(obj); // 20
   var newMethod = method.bind(obj);
   newMethod(); // 20
var userInfo = {
     data: [
       { userName: "zhangsan", age: 20 },
       { userName: "lisi", age: 21 },
     ],
     getUserInfo: function () {
       var index = 1;
      console.log(this.data[index].userName + " "+ this.data[index].age);
     },
   };
   var btn = document.getElementById("btn");
   //btn.onclick = userInfo.getUserInfo;   //this指向btn按钮,函数里的this就指向window,window里没有data属性  
   btn.onclick = userInfo.getUserInfo.bind(userInfo);  
   //将this强制指向userInfo,便可获取到数据
var userInfo = {
  data: [
    { userName: "zhangsan", age: 20 },
    { userName: "lisi", age: 21 },
  ],
  getUserInfo: function () {
  //方法一:
    //   var that = this;
    //   this.data.forEach(function (p) {
    //     console.log(that);    指向对象
    //   });
  //方法二:
  //this.data.forEach((p) => {
     // console.log(this);    指向userInfor
   // });
    this.data.forEach(function (p){   //this指向userInfo
      console.log(this);    //this指向window,闭包环境中,this关键字无法访问或获取到外部函数的this变量
    });
  },
};
var btn = document.getElementById("btn");
btn.onclick = userInfo.getUserInfo.bind(userInfo);

改变this指向的三种方法

硬绑定 => call apply bind

function add(a, b) {
  console.log(this);
  console.log(a + b);
}
function sub(a, b) {
   console.log(a - b);
}
//   add.call(sub, 3, 6);     this指向sub
//   add.apply(sub, [3, 5]);    this指向sub,以数组的形式传参,有隐含作用,可将数组转换为列表
var newFn = add.bind(sub, 3, 3);
newFn();    //this指向sub,返回的是新的函数,随时调用

应用场景1

区别:
call()和apply()会立即执行所调用的函数,参数的传递方式不同,apply以数组的形式传参,
bind()返回的是新的函数,随时调用

//1. 求数组中的最大值和最小值
var arr = [3, 6, 2, 8, 9, 10];
   console.log(Math.max.apply(null, arr));
   console.log(Math.min.apply(null, arr));

//2.将arguments转换为真正的数组
function fn() {
     var arr = Array.prototype.slice.call(arguments);
     arr.push(6);
     return arr;
   }
   console.log(fn(1, 2));

应用场景2

//实现继承
function Person(userName, userAge) {
     this.userName = userName;
     this.userAge = userAge;
   }
   function Student(name, age, gender) {
     Person.call(this, name, age);//Person.call完成对Person函数的调用,this代表Student这个构造函数创建出来的对象student
     this.gender = gender;
   }
   var student = new Student("zhangsan", 20, "男");
   console.log(
     "userName=" +
       student.userName +
       ",userAge=" +
       student.userAge +
       ",gender=" +
       student.gender)
//改变匿名函数this的指向
var person = [
  { id: 1, userName: "zhangsan" },
  { id: 2, userName: "lisi" },
];
for (var i = 0; i < person.length; i++) {
  (function (i) {
    this.print = function () {   //this指向window
      console.log(this.id);     
    };
    this.print();
  }.call(person[i], i));    //改变匿名函数this指向person中的每个对象
}

手动实现call函数

Function.prototype.myCall = function (context) {  //自己定义的函数放到原型对象上,方便后续调用,参数context代表this的指向
  var args = [...arguments].slice(1);
  context = context || window;
  context.fn = this; // Sub.fn=Add    context添加一个属性fn,this指向Add
  var result = context.fn(...args); // Sub.fn(6,3)
  return result;
};
function Add(num1, num2) {
  console.log(this);     //this指向sub
  console.log(num1 + num2);
}
function Sub(num1, num2) {
  console.log(num1 - num2);
}
Add.myCall(Sub, 6, 3);

标签:function,console,log,指向,谈谈,理解,var,obj
From: https://www.cnblogs.com/xiayuxue/p/16614268.html

相关文章

  • 谈谈你对面向对象的理解
    原文:谈谈你对面向对象的理解?、谈一下你对面向对象的理解?。简单修改。将问题的解决抽象为对象执行动作、对象之间相互交互的过程,即面向对象。把具体事物的特定属性和通过......
  • 【Java面试】谈谈常用的分布式ID设计方案
    “谈谈常用的分布式ID设计方案”!一个工作了7年的同学,被问到了这样一个问题。问题并不难,但是在实际面试的时候,如果只是回答1,2,3很难通过面试,因为作为一个高级程序员,还需......
  • Java IO理解
    JavaBIONIOAIO理解同步异步同步:发起一个调用后,被调用者未处理完请求之前,不返回异步:发起一个调用后,立刻得到被调用者的回应表示已接收到请求,但是被调用者并没有返回......
  • 关于IC卡密钥理解和修改(简易篇)
    常用的IC卡由于结构简单,使用方便,价格低,越来越受到普通应用的欢迎.本文主要描述普通IC卡的密钥相关的知识, 关于IC卡的读写,必须使用IC卡读写器,我们推荐使用NFC读写......
  • Vue中bus传值的理解
      说起bus你会想到什么?公交车?总线?在Vue中,对于任意两个组件之间的传值,就可以使用事件总线—bus。简单描述  在任意两个组件传值中,可以创建一个bus类负责事件派发、监听......
  • 深入理解 Spring 事务:入门、使用、原理
    大家好,我是树哥。Spring事务是复杂一致性业务必备的知识点,掌握好Spring事务可以让我们写出更好地代码。这篇文章我们将介绍Spring事务的诞生背景,从而让我们可以更清......
  • Mysql 面试知识点-(理解即可)
    1、关系型和非关系型数据库的区别?关系型数据库的优点-容易理解,因为它采用了关系模型来组织数据。可以保持数据的一致性。数据更新的开销比较小。支持复杂查询(带wher......
  • 对原型链的理解
    目录原型链原型链原型对象在JavaScript中,绝大多数的函数都有一个叫做prototype的属性,指向原型对象,通过构造函数new出来的实例,都可以共享访问原型对象的属性。......
  • vue中的EL理解
    el的作用:用于指明Vue实例的挂载目标。那么什么是挂载?虚拟dom与真实dom建立关系,让Vue实例控制页面中的某个区域的过程,称之为挂载。挂载的方式有:1、通过“el:'css选择器......
  • 2022.8.21 各种锁理解
    21、各种锁理解1、公平锁和非公平锁:公平锁:非常公平,不能够插队,必须先来后到!FIFO非公平锁:非常不公平,可以插队(默认都是非公平)2、可重入锁递归锁  可重入锁sync......