js基础系列之函数调用与this
谁用了this,this就指向谁
函数调用与this的指向
在讲this的指向之前,首先要了解函数的几种调用模式
fun();
obj.method();
fun.call(); / fun.apply(); /fun.bind();
抽象上来看,函数无非就这三种调用模式(new暂且不说),而前两种都是最后一种的语法糖(语法糖就是复杂语法的简便写法),即,任何函数调用的实质都是第三种调用(第三种调用中放的三个例子调用实质是一样的)
函数调用本质上只有这一种形式 fun(context,p1,p2…)
fun()调用
函数调用中最常见的就是fun();形式,如下
fun() === fun.call(undefined)
看如下例子
function Persion(name){this.name=name;
}
Persion('kanggege');
console.log(window.name); //kanggege
在浏览器中,如果call调用传入的context是null或者undefined,则默认的对象是window(严格模式下,依然是undefined)
obj.method()调用
即,方法调用
obj.menthod() === obj.method.call(obj)
看下面的例子
function Persion(name){this.name=name;
}
Persion.prototype.showName=function(){console.log(this.name);
}
var persion = new Persion('kanggege');
persion.showName(); //kanggege
在我是小白的时候(当然现在也超级菜),一直认为这很不科学,因为在Persion.prototype.showName中的this应该指向prototype,即Persion函数的原型对象,但是我们知道,对象可以访问到原型链上的共享属性,但是原型访问不到对象的私有属性,那么console.log(this.name)应当是访问不到的,那是为啥访问到了呢,我们看看调用的实质
persion.showName() === persion.showName.call(persion)
原来this指向了persion,这就很合理了,同时也说明了,实例化的对象中,this指的是对象本身;未实例化中,this指的是实际调用者的对象,通俗的说就是,this的指向是可变的,并不固定,谁调用这个函数,this就指向谁
其他的调用形式
虽然我们说,函数就这三种调用形式,但是这三种调用形式是穿着皇帝的新衣,也有其他的花枝招展的调用形式,但是俗话说的好,关上灯都一样,今天我们就扒光他们的衣服,与我们坦诚相见,看一样不一样
[]形式
var i={f1:function(){console.log(this);}
}
var arr=[i];
arr[0].f1(); //对象i
乍一看,好似this指向的是arr,其实不然,我们扒光衣服再看
arr[0].f1() === arr.0.f1.call(0)
虽然转化后语法是错的,但是我们这里是揭露个实质
Event Handler 中的 this
btn.addEventListener('click' ,function handler(){console.log(this) // 请问这里的 this 是什么
})
MDN上这样说,通常来说this的值是触发事件的元素的引用,这种特性在多个相似的元素使用同一个通用事件监听器时非常让人满意。
当使用 addEventListener() 为一个元素注册事件的时候,句柄里的 this 值是该元素的引用。其与传递给句柄的 event 参数的 currentTarget 属性的值一样。
不要瞎猜,所有this的指向,要么跑不出我们举例的三种情况,要么是特殊的形式,相应文档会给予说明
this用法
引擎调用
foo = function(){this.myName = "Foo function.";
}
foo.prototype.sayHello = function(){console.log(this.myName);
}
foo.prototype.bar = function(){setTimeout(this.sayHello, 1000);
}
var f = new foo;
f.bar(); //undefined
这是因为,当我们用setTimeout来向eventLoop注册函数时,函数是由引擎来发起调用的,因此这个调用者/caller会自动绑定为window
foo = function(){this.myName = "Foo function.";
}
foo.prototype.sayHello = function(){console.log(this.myName);
}
foo.prototype.bar = function(){setTimeout(this.sayHello, 1000);
}
var f = new foo;
foo();
f.bar(); //Foo function
这样就很好的解决了,但是污染了window,不是个好的方式
foo = function(){this.myName = "Foo function.";
}
foo.prototype.sayHello = function(){alert(this.myName);
}
foo.prototype.bar = function(){setTimeout(this.sayHello.bind(this), 1000);//setTimeout(this.sayHello.call(this), 1000);//setTimeout(this.sayHello.apply(this), 1000);
}
var f = new foo;
f.bar()
我们自发的为他绑定上调用的this指向,就不会再被就引擎绑定为window了,很好的解决了这个问题
储存this
var i={};
i.a=1;
i.b=2;
i.num=function(){var that=this;function add(){console.log(that.a+that.b);}add();
}
i.num();
使用that把this储存起来,这样内部变量就可以访问到该方法的对象了,这也是this的一个巧用
链式操作
在jQuery中,我们一般都可以进行$(obj).css().index()等一系列操作,想实现这个原理也极其简单,只需要在调用完后返回调用的对象即可
var obj={name:'kanggege',getName:function(){console.log(this.name);return this;},setName:function(i){this.name=i;return this;}
};
obj.setName('dykanggege').getName(); //dykanggege
就这样,非常简单而又实用的实现了链式操作
js基础系列之函数调用与this相关推荐
- Javascript学习总结 - JS基础系列 二
简述 本系列将持续更新Javascript基础部分的知识,谁都想掌握高端大气的技术,但是我觉得没有一个扎实的基础,我认为一切高阶技术对我来讲都是过眼云烟,要成为一名及格的前端工程师,必须把基础打扎实了 ...
- Javascript学习总结 - JS基础系列三
简述 本系列将持续更新Javascript基础部分的知识,谁都想掌握高端大气的技术,但是我觉得没有一个扎实的基础,我认为一切高阶技术对我来讲都是过眼云烟,要成为一名及格的前端工程师,必须把基础打扎实了 ...
- js 基础 -- 循环、函数调用 、全局和局部变量、异常捕获、事件
一:循环 for for in <!DOCTYPE html> <html> <head><meta charset="utf-8" / ...
- Js基础知识梳理系列
小序:总是感觉自己的技术一直在原地踏步,想学习一些新的技术,但学起来很吃力,而且总是没有什么实际的收获,似乎进入了所谓的"瓶颈期".问了一些前辈是否也遇到过同样的问题,他们给我的解 ...
- 视频教程-零基础JS入门系列课程(2)之JS语法基础精讲-JavaScript
零基础JS入门系列课程(2)之JS语法基础精讲 螺钉课堂讲师,擅长Vue.React.ReactNative.NodeJS等前端框架及技术 邓老师 ¥59.00 立即订阅 扫码下载「CSDN程序员学院 ...
- 【javascript基础——系列10】js中隐藏元素的几种方法以及代码
系列文章 [javascript基础--系列1]前端页面ajax连接后台服务器传输数据 [javascript基础--系列2]前端页面axios连接后台服务器传输数据 [javascript基础--系 ...
- 区块链教程(四):搭建私链、web3.js基础
注:本教程为技术教程,不谈论且不涉及炒作任何数字货币 区块连教程(一):前置知识-linux补充 区块链教程(二):基础概念介绍 区块链教程(三):Solidity编程基础 区块链教程(四):搭建私链 ...
- JavaScript基础系列之五 浏览器
JavaScript基础系列之五 浏览器 浏览器 由于JavaScript的出现就是为了能在浏览器中运行,所以,浏览器自然是JavaScript开发者必须要关注的. 目前主流的浏览器分这么几种: IE ...
- javascript基础系列(入门前须知)
-----------------------小历史---------------------------- javascript与java是两种语言,他们的创作公司不同,JavaScript当时是借 ...
最新文章
- 关于过往与未来的思考
- python画误差棒_给妹子讲python-S02E06matplotlib散点图、频次直方图与误差线图
- python IDLE中反斜杠显示为人民币符号¥的解决办法
- 前端学习(1772):前端调试之serverworkers的概念和方法二
- Opencore-黑苹果:外接4K显示器却只能选择2K或以下分辨率
- php中的递归算法,PHP递归算法(四)
- CVPR 2020 论文大盘点-超分辨率篇
- 快速使用js验证输入的数字类型
- 一个对Winsock完成端口模型封装的类
- 《Java程序员全攻略:从小工到专家》连载二:IT行情分布
- 爬虫_4、requests的post方法以及json字符串处理
- vue改页面顶部浏览器标题栏图标、名称和地址栏详细教程
- STM32F072RB 实作笔记(一)- Keil 安装
- 网络调试分析的工具①
- excel批量删除单元格中的部分内容
- 计算机编程语言排行榜—TIOBE世界编程语言排行榜(2021年08月份最新版)
- assist 下载链接
- uboot什么意思(uboot fastboot)
- 扫地机器人划伤地板_使用扫地机器人地板会被破坏吗
- python调用jsonrpc接口_微信小程序通过jsonrpc调用python服务端接口