JS 里为什么会有 this

目录
  • 1、需求
  • 2、方案
  • 3、第一次改进
  • 4、加糖
  • 5、费解
  • 6、存在问题
  • 7、对象与函数

1、需求

假设我们有一个对象

var person = {
    name: 'Frank',
    age: 18,
    phone: '13812345678',
    sayHi: function(){
      // 待补充
    },
    sayBye: function(){
      // 待补充
    }
}

这个 person 对象有 name age 属性,还有一个 sayHi 方法,现在的需求是:

调用 person.sayHi(...) ,打印出「你好,我是 Frank,今年 18 岁」。
调用 person.sayBuy(...) ,打印出「再见,记得我叫 Frank 哦,想约我的话打电话给我,我的电话是 13812345678」

求就是这么简单,通过达成这个需求,我们就能理解 this 的本质。

2、方案

var person = {
    ...
    sayHi: function(name, age){
      console.log('你好,我是 ${name},今年 ${age} 岁')
    },
    sayBye: function(name, phone){
      console.log('再见,记得我叫 ${name} 哦,想约我的话打电话给我,我的电话是 ${phone}')
    }
}

调用方式是

person.sayHi(person.name, person.age)
person.sayBye(person.name, person.phone)

别急,我知道这代码很傻,接下来改进。

3、第一次改进

上面方法中,每次都要在调用的时候自行选择 person.name 作为参数,真的很傻,不如直接传入一个 person代码如下:

var person = {
    ...
    sayHi: function(self){
      console.log('你好,我是 ${self.name},今年 ${self.age} 岁')
    },
    sayBye: function(self){
      console.log('再见,记得我叫 ${self.name} 哦,想约我的话打电话给我,我的电话是 ${self.phone}')
    }
}

调用方式是

person.sayHi(person)
person.sayBye(person)

稍微好一点了,但是这代码依然很傻。
为什么不能把参数里的 person 省掉,变成 person.sayHi() 就好了。

4、加糖

开发者最想要的调用方式是 person.sayHi()那么问题来了,如果 person.sayHi() 没有实参,person.sayHi 函数是如何接收到 person 的呢?

  • 方法1:依然把第一个参数 self 当做 person,这样形参就会永远比实参多出一个 self
  • 方法2:隐藏 self,然后用关键字 this 来访问 self

JS 之父选择了方法2,用 this 访问 selfPython 之父选择了方法1,留下 self 作为第一个参数。

过程如下:

// 用 this 之前:
sayHi: function(self){
    console.log('你好,我是 ${self.name},今年 ${self.age} 岁')
}
// 用 this 之后:
sayHi: function(){
    // this 就是 self
    console.log('你好,我是 ${this.name},今年 ${this.age} 岁')
}

5、费解

用了 this 之后,完整代码如下:

var person = {
    name: 'Frank',
    age: 18,
    phone: '13812345678',
    sayHi: function(){
      console.log('你好,我是 ${this.name},今年 ${this.age} 岁')
    },
    sayBye: function(){
      console.log('再见,记得我叫 ${this.name} 哦,想约我的话打电话给我,我的电话是 ${this.phone}')
    }
}

现在轮到新手疑惑了,这个 this 到底是个啥玩意儿?从哪来的呀?

实际this 是隐藏的第一个形参。在你调用 person.sayHi() 时,这个 person 会「变成」 this

6、存在问题

很多 JS 高手不屑于用 this,觉得 this 不够单纯。所以 JS 之父给高手们准备了无糖的 .call 方法。

person.sayHi.call(person) 就等价于 person.sayHi()

.call 的第一个参数就是显式的 person,没有任何语法糖。

所以高手一般用 obj.fn.call(null,1,2,3) 来手动禁用 this

这样一来 person.sayHi.call 的参数其实可以是任何对象。

也就是说 person.sayHi 虽然是 person 的方法,但是是可以调用在任何对象上的。

7、对象与函数

JS 没有类没有方法,只有对象和函数。

JS 加了 class 关键字之后,勉强弄出来一个假的类。

this 是连接对象和函数的桥梁。

相比于 JS,我更喜欢 Python 的方式,不使用 this 关键字,而是使用 self 形参,更易懂。

到此这篇关于JS 里为什么会有 this的文章就介绍到这了,更多相关JS 里为什么会有 this内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Javascript中函数分类&this指向的实例详解

    JS中定义函数的三种方式 通过实例来说明吧 <script> //method1 function fn() { console.log('fn created '); } //method2 var fn2 = function () { console.log('fn2 created'); } //method3 var fn3 = new Function('test', 'console.log(test);'); fn3('fn3 test'); console.dir(fn3);

  • JavaScript中的this指向和自定义属性详解

    目录 1.this关键字 2.自定义属性 3.综合案例1:tab选项卡的实现 附录 总结 1.this关键字 this指向的是当前元素 全局函数中的this指向window对象 代码中声明了一个全局函数,是属于浏览器窗口对象的,所以this表示的就是浏览器窗口对象window function fn() { consolo.log(this); } fn() 标签事件属性中的this指向window对象 如果将一个全局函数在一个标签属性中调用,如下: <button onclick="fn

  • JavaScript逐点突破系列之this是什么

    了解this 也许你在其他面向对象的编程语言曾经看过this,也知道它会指向某个构造器(constructor)所建立的对象.但事实上在JavaScript里面,this所代表的不仅仅是那个被建立的对象. 先来看看ECMAScript 标准规范对this 的定义: 「The this keyword evaluates to the value of the ThisBinding of the current execution context.」 「this 这个关键字代表的值为当前执行上下

  • JavaScript中的this指向问题详解

    前言 相信我,只要记住本文的 7️⃣ 步口诀,就能彻底掌握 JS 中的 this 指向. 先念口诀:箭头函数.new.bind.apply 和 call.欧比届点(obj.).直接调用.不在函数里. 按照口诀的顺序,只要满足前面某个场景,就可以确定 this 指向了. 接下来按照口诀顺序对它们进行详解,文中示例代码都运行在 Chrome 的 Console 控制台中. 文末有精心准备的练习题,用于检验学习成果,别忘了试试~ 1. 箭头函数 箭头函数排在第一个是因为它的 this 不会被改变,所以

  • JavaScript函数中this指向问题详解

    this关键字 哪个对象调用函数,函数里面的this指向哪个对象. **严格模式下:**在全局环境中,this指向的是undefined **非严格模式下:**在全局环境中,this指向的是window 全局定义的函数直接调用,this => window function fn(){ console.log(this); // 此时 this 指向 window } fn(); // 相当于 window.fn() 对象内部的函数调用,this => 调用者 var obj = { fn:f

  • JavaScript 中this指向问题案例详解

    总结 全局环境 ➡️ window 普通函数 ➡️ window 或 undefined 构造函数 ➡️ 构造出来的实例 箭头函数 ➡️ 定义时外层作用域中的 this 对象的方法 ➡️ 该对象 call().apply().bind() ➡️ 第一个参数 全局环境 无论是否在严格模式下,this 均指向 window 对象. console.log(this === window) // true // 严格模式 'use strict' console.log(this === window

  • 基于js里调用函数时,函数名带括号和不带括号的区别

    示例代码: <span style="font-size:18px;">function hi(){ var a = 1; return function(){ console.log(a++); }; }; var aaa = hi(); var bbb = hi; </span> 如以上代码: aaa 是将 hi() 的运行结果赋值给它,即 return 返回的匿名函数,此时有一个闭包,则每次调用 aaa 时都访问的同一个 a,aaa() 第一次运行结果为

  • 直接在JS里创建JSON数据然后遍历使用

    之前我已经有讲过后台返回json数据到前台,并在前台遍历json数据. 这里讲下直接在JS里创建JSON数据,然后遍历使用~ 创建代码如下:(创建的是JSON对象) var YearSelect = {}; var Year = 2014; var DateOption; for (var i = Year; i < Year + 12; i++) { DateOption = {'Year':i, 'Month':i-Year+1}; / alert(DateOption.Year) Year

  • 注释的艺术——JS里直接写HTML,无需转义

    利用JS的多行注释配合函数的直接量可以做到JS里直接写HTML代码,除 script 的结束标签之外,无需任何的转义符和续行符. //Code By Dron //Ucren.com document.write((function (){/* Hello Word! alert("Hello Word!"); */}).toString().replace(/^.+?\*|\\(?=\/)|\*.+?$/gi, "")); [Ctrl+A 全选 注:如需引入外部J

  • 地址栏传递中文参数乱码在js里用escape转码

    乱码,乱码,头大,烦,话说设置Tomcat后可以解决,但有的时候不管用了,这时,我们可以考虑转码方式不直接传中文,在js里用escape转码,记得需要用两次,如: var str=escape("这是中文参数"); str=escape(str); xxx.do?name=str; 在后台通过一个类的方法再转回来: Escape.unescape(request.getParameter("name")); Escape类如下: 复制代码 代码如下: package

  • 关于js里的this关键字的理解

    this关键字在c++,java中都提供了这个关键字,在刚开始学习时觉得有难度,但是只要理解了,用起来就方便多了,下面通过本篇文章给大家详解js里this关键字的理解. 关于this,是很多前端面试必考的题目,有时候在网上看到这些题目,自己试了一下,额,还真的错了!在实际开发中,也会遇到 this 的问题(虽然一些类库会帮我们处理),例如在使用一些框架的时候,例如:knockout,有时候不明白为什么不直接使用this,而要把 this 作为参数传入. 接下来你谈谈我对它的理解,也作为一个笔记,

  • 在js里怎么实现Xcode里的callFuncN方法(详解)

    本人使用的WebStorm编辑器,里面没有callFuncN, 不记得Lua是否支持callFuncN,如果不支持相信应该能用同样的方法做到. 废话不多说,贴代码: loadDown : function () { var dis = this.left_move.getPositionY() - this.left.getPositionY(); // 得到一个距离 var act1 = new cc.moveBy(0.5,cc.p(0,-dis)); var act2 = cc.callFu

  • 微信小程序引用公共js里的方法的实例详解

    微信小程序引用公共js里的方法的实例详解 一个小程序页面由四个文件组成,一个小程序页面的四个文件具有相同路径与文件名,由此我们可知一个小程序页面对应着一个跟页面同名的js文件.可是当有些公共方法,我们想抽离出来成为一个独立公共的js文件.我们该如何实现呢. 在根目录下有一个app.js文件.这个根目录的js 文件我们可以通过getApp()轻松调用. //app.js App({ globaData:'huangenai' }) //test.js var app = getApp(); Pag

  • 浅谈js里面的InttoStr和StrtoInt

    javascript 字符串 和 数字的转换,话说好灵活,感觉回不去pascal了 int转换string: 1,var str=String(int); 2,num.toString(param) ; // param 为进制 eg: var num=100; num.toString(16); result= $64h; 3,num.toFixed(param); // param 为小数点位数(还带进位,太好用了). eg: var num=100; num.toString(1); re

  • 详解Js里的for…in和for…of的用法

    之前看编程方法学,for循环的基本格式是 for(init;test;step ){ statement } //例如 for(int i=0,i<10;i++){ ... } 后来接触了python,for循环的格式更加的简单优雅,只要一个for --in语句就可以直接遍历对象. for i in arry 今天看廖雪峰的官网,居然看到了js里更神奇的操作,for --of循环,这个类似于python的for --in循环了,虽然js里也有for --in循环,可是遍历的是对象的属性,类似于键

  • vue 获取及修改store.js里的公共变量实例

    html <input type='text' :value='num'> <button @click='add'> + </botton> js data(){ return{ } }, methods:{ add(){ this.$store.commit('add',1) } }, computed:{ num:function(){ // 因为要做修改 num 的值 所以放在 计算属性里 return this.$store.state.num } } sto

随机推荐