深入浅出javascript(八)this、call和apply
_________此篇日志属于重要记录,长期更新__________
this,call,apply这三个是进阶JS的重要一步,需要详细的记录。
➢ this
一、作为对象的方法调用。
当函数作为对象的方法被调用时,this指向该对象。
首先,函数必须作为对象的方法。这句话很关键,因为函数的调用有很多种可能,在后面会展现。示例1-1:
var o = {
name: 'o',
get: function () {
return this.name;
}
}
console.log(o.get());//输出'o'
get方法是被对象o调用的,所以this指向o,这是没有异议的。
现在把这个例子改下,示例1-2:
var o = {
name: 'o',
get: function () {
return this.name;
}
};
var g = o.get; //将o的get方法赋给g;
console.log(g()); //输出空;
o.get方法赋给g之后,现在这个方法g和原来的对象o已经没有关系了,因为g是全局的,所以它属于window的方法,结果导致方法内的this已经指向window,又,window没有定义name属性,所以输出为空。
从这两个例子的对比可以看出,this是随机而动的,谁绑定,this就指向谁。
二、做为普通函数调用
这里所说的普通函数调用主要是为了和狭隘的 ' 对象的方法调用 ' 来区别。因为无论函数怎么调用,它总属于一个对象,因为最外层总有一个window对象。
如上例所示,将函数赋值给另一个变量,就是将这个函数从对象中 ’ 复制一份 ‘ 出来,结果变成window对象的一个方法,因此this指向window。
示例2-1

1.创建变量o,因为是全局的,所以内部的this为window,其内部的g也属于普通函数调用,因此也指向this。
三、函数到底出现在哪儿?
函数到底出现在哪里,说的是函数究竟出现在哪种地方,只有将出现的这几种地方弄明白,才能对函数做更深入的了解,总结如下:
| 1 | 普通函数 |
| 2 | 普通函数内部的普通函数 |
| 3 | 对象内部 |
| 4 | 对象内部的函数的内部 |
➢ 四种可能:
|
普通函数 this=window |
普通函数内部的普通函数 this=window |
对象内部函数 this=对象 |
对象内部函数内部的普通函数 this=window |
|
function f() { |
function f() { |
var o = { |
var o = { |
现在可以推断两条结论:
一、凡是普通函数都指向window
二、凡是对象调用都指向对象。(这里的对象是狭隘的对象,即自创建的对象)
换句话说,凡遇到一个函数,首先两问:
一、这个函数是普通函数吗?[如果是,则this=window]
二、这个函数是被对象调用的吗?[如果是,则this=对象]
※ 回过头再看前面的一句话:当函数作为对象的方法被调用时,this指向该对象,也就可以理解了。
四、做为构造函数
做为构造函数比较简单,this指定绑定的对象。仅示例:
var F = function () {
this.name = 'F';
};
var f=new F();
➢ apply和call
一、概述

apply就是函数调用,而调用的就是函数fn,也就是说执行fn( )。 apply后面是(对象,参数)。参数可以是数组,可以是➀类数组。
所以理解这个apply就是记住两个点:
1.调用函数fn.
2.传入对象,如果传入的对象为null,则this=window
apply概括:调用函数fn,fn需要依赖传入的对象来确定它内部的this到底指向谁。
示例1-1:
window.name = 'window';
function f() {
console.log(this.name);
}
f.apply(null); //输出'window'
首次接触的时候有点点绕。
示例1-2:
function f() {
console.log(this.name);
}
var o = {
name: '对象o'
};
f.apply(o);
二、作用
1、改变this的指向
首先,这个this指的是谁呢?肯定是fn内部的this。如果函数没有this,那又何谈改变this的指向呢。现在先做一个带有this的函数。
function f() {
console.log(this.name);
}
this是可以随意绑定的,这就是apply的作用,做个图示例一下:

function f() {
console.log(this.name);
}
var o = {
name: 'o'
};
如上代码所示,f.apply(o),f内部的this绑定了对象o。
2、借用其它对象的方法——继承
这种继承是继承方法中的一种 [ 关于Javascript继承详细,参看记录 ],其实说起来更像是 ‘复制’。即:将父类中的属性复制一份到子类,代码2-1:
/***构造继承最简化的形式***/
//父类
function subClass() {
this.name = 'subClass';
}
//子类
function superClass() {
subClass.call(this);
}
var o = new superClass();
console.log(o.name); //输出'subclass'
➢ 代码解析:
子类构造函数使用父类.call,并将子类自己的this代入,结果就是将父类的属性 '复制' 了一份给子类。
3、类数组的使用(重要!)
补充于2018-10-23 20:12:51
类数组一个比较常见的例子是arguments。这个东西像数组但又不是数组,如果采用一般的数组方法是不可行的,必须采用数组的call调用。
示例如下:
arguments.join(","),#这条语句希望将函数参数用","连接起来形成字符串,但是代码错误不能通过。这里采用Array原型方法调用:
Array.prototype.join.call(arguments,",");
这一条的应用比较常用且重要,也是采用call调用的一个比较独特的例子。
4、
深入浅出javascript(八)this、call和apply的更多相关文章
- Javascript中call函数和apply函数的使用
Javascript 中call函数和apply的使用: Javascript中的call函数和apply函数是对执行上下文进行切换,是将一个函数从当前执行的上下文切换到另一个对象中执行,例如: so ...
- 深入浅出 JavaScript 对象 v0.5
JavaScript 没有类的概念,因此它的对象与基于类的语言中的对象有所不同.笔者主要参考<JS 高级程序设计>.<JS 权威指南>和<JS 精粹> 本文由浅入深 ...
- 从头开始学JavaScript (八)——变量
原文:从头开始学JavaScript (八)--变量 一.变量分类: 基本类型值:null.undefined.number.string.Boolean: 引用类型值:保存在内存中的对象,如:Obj ...
- 深入浅出 JavaScript 关键词 -- this
深入浅出 JavaScript 关键词 -- this 要说 JavaScript 这门语言最容易让人困惑的知识点,this 关键词肯定算一个.JavaScript 语言面世多年,一直在进化完善,现在 ...
- Javascript 中的 call 和 apply
发表于 2012年02月1日 by 愚人码头 原文链接:http://www.css88.com/archives/4431 JavaScript 中通过call或者apply用来代替另一个对象调 ...
- 深入浅出JavaScript之this
JavaScript中的this比较灵活,根据在不同环境下,或者同一个函数在不同方式调用下,this都有可能是不同的.但是有一个总的原则,那就是this指的是,调用函数的那个对象. 下面是我的学习笔记 ...
- 【转】深入浅出JavaScript之this
JavaScript中的this比较灵活,根据在不同环境下,或者同一个函数在不同方式调用下,this都有可能是不同的.但是有一个总的原则,那就是this指的是,调用函数的那个对象. 下面是我的学习笔记 ...
- javascript中call函数与apply
javascript中的call方法使当前对象可以调用另一个对象的方法,即改变this的指向内容 var first_object = { num: 42 }; var second_object = ...
- 深入浅出 JavaScript 中的 this
在 Java 等面向对象的语言中,this 关键字的含义是明确且具体的,即指代当前对象.一般在编译期确定下来,或称为编译期绑定.而在 JavaScript 中,this 是动态绑定,或称为运行期绑定的 ...
随机推荐
- java 向上转型和向下转型
学习向上转型和向下转型怎么用没多难,但是为什么那样用,我搞了很多次没弄明白.没弄明白的原因是平时学习时之看例子,而例子一般都比较简单,没有对象之间的调用,一般就是一个对象调用自己的方法. 首先看下怎么 ...
- Sobel Derivatives
https://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.html ...
- 将文件转换成byte[]数组
代码 /// <summary> /// 将文件转换成byte[] 数组 /// </summary> /// <param name="fileUrl&quo ...
- MVC防止跨站攻击@Html.AntiForgeryToken()
ASP.NET MVC 中有个标签:@Html.AntiForgeryToken(),需要在页面中加入这个标签,然后在Actoin中加入特性[ValidateAntiForgeryToken]就可以了 ...
- 在threejs中添加两个场景和相机是需要注意render的参数设置
问题:我刚开始设置了两个场景和相机 但是第二个一直将第一个场景给覆盖了一直找不到原因 解决: 问题出在 renderer.autoClear = false;上 设置render的参数如下: rend ...
- DirectX中坐标系问题
自己属于笨类型,以前总是记不住directx坐标系是怎样的,今天在网上看到一篇文章,借鉴过来. 1. 明确DirectX是左手坐标系. 描述如下:1. 伸出左手,手面朝上,手背朝下,握住z轴,大拇指方 ...
- Centos7上安装docker及使用scrapy-splash
下载docker https://www.cnblogs.com/yufeng218/p/8370670.html 安装scrapy-splash https://www.cnblogs.com/ ...
- DevExpress中RibbonControl的简单应用
现在介绍一下DevExpress中的RibbonControl的简单应用,搭建一个拥有Office2010风格的窗体程序. 第一步:打开VS2015,新建一个windows窗体应用程序: 第二步:把需 ...
- devexpress之barManager 使用
这次我不想使用ribboncontrol 控件 作为窗口菜单栏,也不想用传统的那种字体的方式 标题栏 一.Bars 1. 把BarManager组件添加到窗体中后,会自动创建两个空的 bars: ...
- JQuery.validate 错误信息对话框
<script src="${pageContext.request.contextPath}/static/js/jquery-1.12.1.js"type="t ...