06.Javascript——入门this的用法(难点)
this 的指向
this 是 js 中定义的关键字,它自动定义于每一个函数域内,但是它的指向却让人很迷惑。在实际应用中,this 的指向大致可以分为以下四种情况。
1.作为普通函数调用
当函数作为一个普通函数被调用,this 指向全局对象。在浏览器里,全局对象就是 window。
window.name = 'linxin';
function getName(){
console.log(this.name);
}
getName(); // linxin
可以看出,此时 this 指向了全局对象 window。 在ECMAScript5的严格模式下,这种情况 this 已经被规定不会指向全局对象了,而是 undefined。
'use strict';
function fun(){
console.log(this);
}
fun();
2.作为对象的方法调用
当函数作为一个对象里的方法被调用,this 指向该对象
var obj = {
name : 'linxin',
getName : function(){
console.log(this.name);
}
} obj.getName(); // linxin
如果把对象的方法赋值给一个变量,再调用这个变量:
var obj = {
fun1 : function(){
console.log(this);
}
}
var fun2 = obj.fun1;
fun2(); // window
此时调用 fun2 方法 输出了 window 对象,说明此时 this 指向了全局对象。给 fun2 赋值,其实是相当于:
var fun2 = function(){
console.log(this);
}
可以看出,此时的 this 已经跟 obj 没有任何关系了。这时 fun2 是作为普通函数调用。
3.作为构造函数调用
js中没有类,但是可以从构造器中创建对象,并提供了 new 运算符来进行调用该构造器。构造器的外表跟普通函数一样,大部分的函数都可以当做构造器使用。当构造函数被调用时,this 指向了该构造函数实例化出来的对象。
var Person = function(){
this.name = 'linxin';
}
var obj = new Person();
console.log(obj.name); // linxin
如果构造函数显式的返回一个对象,那么 this 则会指向该对象。
var Person = function(){
this.name = 'linxin';
return {
name : 'linshuai'
}
}
var obj = new Person();
console.log(obj.name); // linshuai
如果该函数不用 new 调用,当作普通函数执行,那么 this 依然指向全局对象。
4.call() 或 apply() 调用
通过调用函数的 call() 或 apply() 方法可动态的改变 this 的指向。
var obj1 = {
name : 'linxin',
getName : function(){
console.log(this.name);
}
}
var obj2 = {
name : 'linshuai'
} obj1.getName(); // linxin
obj1.getName.call(obj2); // linshuai
obj1.getName.apply(obj2); // linshuai
apply 和 call 的区别
ECMAScript 规范给所有函数都定义了 call 与 apply 两个方法,它们的应用非常广泛,它们的作用也是一模一样,只是传参的形式有区别而已。
apply( )
apply 方法传入两个参数:一个是作为函数上下文的对象,另外一个是作为函数参数所组成的数组。
var obj = {
name : 'linxin'
} function func(firstName, lastName){
console.log(firstName + ' ' + this.name + ' ' + lastName);
} func.apply(obj, ['A', 'B']); // A linxin B
可以看到,obj 是作为函数上下文的对象,函数 func 中 this 指向了 obj 这个对象。参数 A 和 B 是放在数组中传入 func 函数,分别对应 func 参数的列表元素。
call( )
call 方法第一个参数也是作为函数上下文的对象,但是后面传入的是一个参数列表,而不是单个数组。
var obj = {
name: 'linxin'
} function func(firstName, lastName) {
console.log(firstName + ' ' + this.name + ' ' + lastName);
} func.call(obj, 'C', 'D'); // C linxin D
对比 apply 我们可以看到区别,C 和 D 是作为单独的参数传给 func 函数,而不是放到数组中。
对于什么时候该用什么方法,其实不用纠结。如果你的参数本来就存在一个数组中,那自然就用 apply,如果参数比较散乱相互之间没什么关联,就用 call。
apply 和 call 的用法
1.改变 this 指向
var obj = {
name: 'linxin'
} function func() {
console.log(this.name);
} func.call(obj); // linxin
我们知道,call 方法的第一个参数是作为函数上下文的对象,这里把 obj 作为参数传给了 func,此时函数里的 this 便指向了 obj 对象。此处 func 函数里其实相当于
function func() {
console.log(obj.name);
}
2.借用别的对象的方法
var Person1 = function () {
this.name = 'linxin';
}
var Person2 = function () {
this.getname = function () {
console.log(this.name);
}
Person1.call(this);
}
var person = new Person2();
person.getname(); // linxin
从上面我们看到,Person2 实例化出来的对象 person 通过 getname 方法拿到了 Person1 中的 name。因为在 Person2 中,Person1.call(this) 的作用就是使用 Person1 对象代替 this 对象,那么 Person2 就有了 Person1 中的所有属性和方法了,相当于 Person2 继承了 Person1 的属性和方法。
3.调用函数
apply、call 方法都会使函数立即执行,因此它们也可以用来调用函数。
function func() {
console.log('linxin');
}
func.call(); // linxin
call 和 bind 的区别
在 EcmaScript5 中扩展了叫 bind 的方法,在低版本的 IE 中不兼容。它和 call 很相似,接受的参数有两部分,第一个参数是是作为函数上下文的对象,第二部分参数是个列表,可以接受多个参数。
它们之间的区别有以下两点。
1.bind 发返回值是函数
var obj = {
name: 'linxin'
} function func() {
console.log(this.name);
} var func1 = func.bind(obj);
func1(); // linxin
bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。而原函数 func 中的 this 并没有被改变,依旧指向全局对象 window。
2.参数的使用
function func(a, b, c) {
console.log(a, b, c);
}
var func1 = func.bind(null,'linxin'); func('A', 'B', 'C'); // A B C
func1('A', 'B', 'C'); // linxin A B
func1('B', 'C'); // linxin B C
func.call(null, 'linxin'); // linxin undefined undefined
call 是把第二个及以后的参数作为 func 方法的实参传进去,而 func1 方法的实参实则是在 bind 中参数的基础上再往后排。
在低版本浏览器没有 bind 方法,我们也可以自己实现一个。
if (!Function.prototype.bind) {
Function.prototype.bind = function () {
var self = this, // 保存原函数
context = [].shift.call(arguments), // 保存需要绑定的this上下文
args = [].slice.call(arguments); // 剩余的参数转为数组
return function () { // 返回一个新函数
self.apply(context,[].concat.call(args, [].slice.call(arguments)));
}
}
}
06.Javascript——入门this的用法(难点)的更多相关文章
- JavaScript入门笔记
第一章 JavaScript语法 1.1 初识JavaScript 1.3 数据类型 1.4 string和boolean类型 1.5 算数操作符 第二章 JavaScript流程控制语句 2.1 循 ...
- 慕课网JavaScript入门篇课程笔记
1.js注释很重要 单行注释,在注释内容前加符号 “//”. <script type="text/javascript"> document.write(" ...
- 开心菜鸟系列----函数作用域(javascript入门篇)
1 <!DOCTYPE html> 2 <html> 3 <script src="./jquery-1.7.2.js"></ ...
- javascript入门视频第一天 小案例制作 零基础开始学习javascript
JavaScript 是我们网页设计师必备的技能之一.我们主要用javascript来写的是网页特效.我们从零基础开始学习javascript入门. 但是,好的同学刚开始不知道怎么学习,接触js,因此 ...
- JavaScript入门篇
记录一下在慕课网学习JavaScript的过程. 以下内容均来自慕课网. 传送:https://www.imooc.com/code/401 为什么学习JavaScript 1. 所有主流浏览器都支持 ...
- JavaScript入门--慕课网学习笔记
JAVASCRIPT—(慕课网)入门篇 我们来看看如何写入JS代码?你只需一步操作,使用<script>标签在HTML网页中插入JavaScript代码.注意, <script&g ...
- JavaScript 入门案例
四. JavaScript 入门案例 在看本节之前,笔者建议您先看 JavaScript 基础篇 https://www.cnblogs.com/IT-LFP/p/10945884.html 1. ...
- JavaScript入门篇 编程练习
编程挑战 一.定义"改变颜色"的函数 提示: obj.style.color obj.style.backgroundColor 二.定义"改变宽高"的函数 提 ...
- javascript confirm()函数的用法
javascript confirm()函数的用法 confirm():确认消息对话框.用于允许用户做选择的动作.弹出的对话框中包含一确定按钮和一取消按钮. confirm(str) 参数说明: st ...
随机推荐
- poj3565Ants——KM算法
题目:http://poj.org/problem?id=3565 首先,我们神奇地发现,没有相交边的匹配可以转化为距离和最小的匹配,所以可以使用KM算法求带权匹配: 要求的是距离和最小,所以把边权转 ...
- es6 import 报错
现在绝大多数的浏览器都不支持ES6,所以使用es6时需要使用bebal把es6转化为es5, 项目目录: demo1:单个js文件的转化 src文件下的 test1.js const aa=" ...
- webpack 知识点总结
1 webpack 的不同点: 1.1 实现代码分割 1.2 loaders 1.3 plugin system 2 webpack 打包css,需要使用css-loaders 使webpack识别c ...
- sqlserver——视图
数据库中的视图是一个虚拟表.同真实的表一样,视图包含一系列带有名称的列和行数据,行和列数据用来自由定义视图和查询所引用的表,并且在引用视图时动态产生.本篇将通过一些实例来介绍视图的概念,视图的作用,创 ...
- [WIP]express 入门
创建: 2019/04/10 install 创建并移动进新文件夹 mkdir sample_app cd sample_app 创建package.json并导入express npm ini ...
- 洛谷 - P1390 - 公约数的和 - 莫比乌斯反演 - 欧拉函数
https://www.luogu.org/problemnew/show/P1390 求 $\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m} gcd(i,j) $ ...
- BlocksKit的使用
一.引言 众所周知Block已被广泛用于iOS编程.它们通常被用作可并发执行的逻辑单元的封装,或者作为事件触发的回调.Block比传统回调函数有2点优势: 允许在调用点上下文书写执行逻辑,不用分离函数 ...
- ASPNET-ASPNETCORE 认证
话题背景 关于认证我的个人理解是,验证信息的合法性.在我们生活当中,比如门禁,你想进入一个有相对安全措施的小区或者大楼,你需要向保安或者门禁系统提供你的身份信息证明,只有确定你是小区业主,才可以进来, ...
- 渗透测试之无文件渗透简单使用-windows
无文件渗透测试工作原理:无文件恶意程序最初是由卡巴斯基在2014年发现的,一直不算是什么主流的攻击方式,直到此次事件的发生.说起来无文件恶意程序并不会为了执行而将文件或文件夹复制到硬盘上,反而是将pa ...
- 2018全球十大测试工具Top2 Katalon
引言 由Capgemini,Sogeti和Micro Focus发布的2017-2018年世界质量报告中,Katalon超越老牌测试工具UFT(源自QTP)成为黑马新秀,在全球十大自动化测试工具中排名 ...