JS-12-关键字this、apply()、call()

一、对象的方法

在一个对象中绑定函数,称为这个对象的方法。

示例:

1、对象:

var xiaoming = {name: '小明',birth: 1990
};

2、给xiaoming绑定一个函数。比如,写个age()方法,返回xiaoming的年龄:

var xiaoming = {name: '小明',birth: 1990,age: function () {var y = new Date().getFullYear();return y - this.birth; // this关键字}
};xiaoming.age; // 整个function代码
xiaoming.age(); // 今年调用是25,明年调用就变成26了

绑定到对象上的函数称为方法,和普通函数也没啥区别,但是它在内部使用了一个this关键字。

二、this关键字

在一个方法内部,this是一个特殊变量,它始终指向当前对象,也就是xiaoming这个变量。所以,this.birth可以拿到xiaoming的birth属性。

function getAge() {var y = new Date().getFullYear();return y - this.birth;
}var xiaoming = {name: '小明',birth: 1990,age: getAge // age获取整个getAge这个函数的代码
};xiaoming.age(); // 25, 正常结果
getAge(); // NaN

问题来了:单独调用函数getAge()怎么返回了NaN。

因为这个JavaScript的函数内部调用了this,而这个this到底指向谁,视情况而定:

1、如果以对象的方法形式调用,比如xiaoming.age(),该函数的this指向被调用的对象,也就是xiaoming,这是符合我们预期的。

2、如果单独调用函数,比如getAge(),此时,该函数的this指向全局对象,也就是window。

更坑爹的是,如果这么写:

var fn = xiaoming.age; // 先拿到xiaoming的age函数
fn(); // NaN

也是不行的!要保证this指向正确,必须用obj.xxx()的形式调用

3、方法重构

'use strict';var xiaoming = {name: '小明',birth: 1990,age: function () {function getAgeFromBirth() {var y = new Date().getFullYear();return y - this.birth;}return getAgeFromBirth();}
};xiaoming.age(); // Uncaught TypeError: Cannot read property 'birth' of undefined

结果又报错了!

原因是this指针只在age方法的函数内指向xiaoming,在函数内部定义的函数,this又指向undefined了!(在非strict模式下,它重新指向全局对象window!)

纠正的方式:

1、ECMA决定,在strict模式下让函数的this指向undefined,因此,在strict模式下,你会得到一个错误:

'use strict';var xiaoming = {name: '小明',birth: 1990,age: function () {var y = new Date().getFullYear();return y - this.birth;}
};var fn = xiaoming.age;
fn(); // Uncaught TypeError: Cannot read property 'birth' of undefined

这个决定只是让错误及时暴露出来,治标不治本。

2、方法重构

我们用一个that变量首先捕获this:

'use strict';var xiaoming = {name: '小明',birth: 1990,age: function () {var that = this; // 在方法内部一开始就捕获thisfunction getAgeFromBirth() {var y = new Date().getFullYear();return y - that.birth; // 用that而不是this}return getAgeFromBirth();}
};xiaoming.age(); // 25

var that = this;,你就可以放心地在方法内部定义其他函数

三、apply方法-控制this的指向

在一个独立的函数调用中,根据是否是strict模式,this指向undefined或window。

要指定函数的this指向哪个对象,可以用函数本身的apply方法

apply方法接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。

 

function getAge() {var y = new Date().getFullYear();return y - this.birth;
}var xiaoming = {name: '小明',birth: 1990,age: getAge
};xiaoming.age(); // 25
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空

四、call方法-控制this的指向

另一个与apply()类似的方法是call(),唯一区别是:

  • apply()把参数打包成Array再传入;
  • call()把参数按顺序传入。

比如调用Math.max(3, 5, 4),分别用apply()和call()实现如下:

Math.max.apply(null, [3, 5, 4]); // 5
Math.max.call(null, 3, 5, 4); // 5

对普通函数调用,我们通常把this绑定为null。

五、装饰器

利用apply(),我们还可以动态改变函数的行为。

JavaScript的所有对象都是动态的,即使内置的函数,我们也可以重新指向新的函数。

假定我们想统计一下代码一共调用了多少次parseInt(),可以把所有的调用都找出来,然后手动加上count += 1,不过这样做太傻了。最佳方案是用我们自己的函数替换掉默认的parseInt():

var count = 0;
var oldParseInt = parseInt; // 保存原函数window.parseInt = function () {count += 1;return oldParseInt.apply(null, arguments); // 调用原函数
};// 测试:
parseInt('10');
parseInt('20');
parseInt('30');
console.log('count = ' + count); // 3

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/745127.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SwiftUI的context Menu

SwiftUI的 context Menu 现在来演示一下如何使用 SwiftUI 的 Context Menu 。 代码: import SwiftUIstruct ContextMenuBootCamp: View {State var bgColor: Color .purplevar body: some View {VStack(alignment: .leading, spacing: 10.0) {Image(systemName: …

音视频实战---从音视频文件中提取h264裸流

1、使用avformat_alloc_context分配解复用器上下文内存 2、使用avformat_open_input打开音视频文件或网络流 3、使用avformat_find_stream_info获取码流信息 4、使用 av_find_best_stream获取视频流下标 5、分配编码数据av_packet_alloc内存空间 6、使用av_init_packet初始…

Filebeat rpm方式安装及配置

一、使用服务器root用户、filebeat8.11.1版本,rpm安装方式进行安装 curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.11.1-x86_64.rpm sudo rpm -vi filebeat-8.11.1-x86_64.rpm 二、配置核心的采集文件、使用inputs热更方式、配置filebeat本身…

LLVM-3.5 —— 01记,编译 LLVM 3.5.0 clang and clang-query

包括编译:clang clang-tools-extra 0, prepare env sudo apt install llvm sudo apt install clang 使用最新的g 会出错。 1, source code $ git clone --recursive $ cd llvm-project $ git checkout llvmorg-3.5.0 $ cp -r ./clang ./llvm/tools/ $ mkdir llv…

LeetCode202.快乐数

202快乐数 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。 如果这个过程 结果为 1&…

python爬虫(10)之get()函数

1、headers 用于设置请求包中的请求头信息(在很多网站会在那个请求包头加一层验证来防止他人爬取数据) 当然前面已经讲过它是在哪里找 2、params 是用于模拟在发送动态请求时携带动态参数这种常用于那种在搜索框来进行爬取的行为 3、timeout 设置超…

冥想与AI:打造定制的放松体验

如今,在浏览网页或社交网络时,您似乎很难对一条条心理健康信息无动于衷。遇到这种情况的可不只是您。当今不断变化的时代给人们平添压力,企业纷纷利用智能技术满足人们的减压需求,让人们的生活多一些平和从容。 冥想就是一种练习呼…

客户满意度提升:电商平台使用API改善客户服务体验

客户满意度是电商平台成功的关键指标之一,而提供卓越的客户服务体验是提升满意度的重要途径。API(应用程序编程接口)在这一过程中扮演着至关重要的角色,因为它能够提高服务效率、个性化用户体验并确保信息的一致性。以下是电商平台…

HDOJ 2044

一只小蜜蜂… Problem Description 有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行。请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线数。 其中,蜂房的结构如下所示。 Input 输入数据的第一行是一个整数N,表示测试实例的个数,然后是N…

高效Go编程: encoding/csv标准库深度解析

高效Go编程: encoding/csv标准库深度解析 引言了解encoding/csv库CSV文件的基本结构encoding/csv库的核心功能应用场景 读取CSV文件基本步骤代码示例处理不同的分隔符错误处理 处理CSV数据数据解析代码示例处理不规则数据代码示例 写入CSV文件基本步骤代码示例自定义设置错误处…

Vue组件之间的通信方式

文章目录 组件间通信的概念组件间通信的分类组件间通信的方案父组件将方法传递给子组件(props)子组件向父组件传值(emit)通过 ref 属性获取DOM元素EventBus p a r e n t 或 parent 或 parent或 root a t t r s 与 attrs 与 attrs与 listeners provide 与…

Kotlin编程权威指南学习知识点预览

一、变量、常量和类型: 变量、常量以及 Kotlin 基本数据类型。变量和常量在 应用程序中可用来储值和传递数据。类型则用来描述常量或变量中保存的是什么样的数据。 1、声明变量: // 变量定义关键字 —— 变量名 —— 类型定义 —— 赋值运算符 —— 赋值var na…

cesium wall 扩散墙(动态立体墙效果 Primitive 方法)

cesium wall 扩散墙(动态立体墙效果)以下为源码直接复制可用 1、实现思路 1、此效果运用cesium 中 Primitive 方法,通过传入中心点、半径、顶点数、颜色来进行加载。 2、运用 Math 方法 对传进来的中心点、半径、定点数,来计算个顶点经纬度。 3、通过Primitive 方法中upda…

643.子数组最大平均数

题目:给你一个由 n 个元素组成的整数数组 nums 和一个整数k。 找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数。 任何误差小于10^-5 的答案都将被视为正确答案。 解题思路:规定了子数组的长度为k,因此可以通过寻找子…

洛谷——P1352 没有上司的舞会

题目描述 某大学有 n 个职员,编号为1…n。 他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。 现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数 ri​,但…

RocketMQ如何实现消息的顺序性

首先,以订单举例,要实现顺序性,并不需要保证各个订单的顺序性,只需保证一个订单中各个操作的顺序性即可。 简单来说: 就是把同一个订单的操作,比如下单付款发货,按顺序放到一个Message Queue里…

vector与list的区别与应用?

vector与list的区别与应用?以及怎么找到某vector或者list的倒数第二个元素? vector和list的区别可以类比数组和链表的区别: vector和数组类似,vector是一个在内存中连续存放且可以自动增长的容器,因此支持随机访问&am…

15、Linux-Shell04:分支和循环

一、分支逻辑 1、if if condition1 thencommand1 elif condition2 then command2 elsecommandN fiecho please input first number read a echo please input second number read bif [ $a -eq $b ] thenecho "equal" elif [ $a -gt $b ] thenecho "the firs…

【MySQL】深入解析索引实现原理

文章目录 1、索引介绍2、索引分类2.1、数据结构HashB Tree 2.2、存储方式聚簇索引非聚簇索引 2.3、功能特性主键索引唯一索引普通索引 2.4、字段数量单列索引多列索引 3、最佳实践3.1、索引覆盖3.2、回表操作3.3、最左匹配原则3.4、索引下推 1、索引介绍 对于MySQL数据库来说…

笔试题:小红的循环小数 数论 欧拉 快速幂 小费马定理

小红的循环小数 众所周知,所有的无限循环小数都可以写成分数的形式 小红想让你判断循环节长度为k的无限循环小数的分母是否可能是p。你能帮帮她吗? 共有q次询问。 输入描述 第一行输入一个正整数 q q q,代表询问次数。 接下来的 q q q行&…