前端总结·基础篇·JS(三)arguments、callee、call、apply、bind及函数封装和构造函数
前端总结系列
- 前端总结·基础篇·CSS(一)布局
- 前端总结·基础篇·CSS(二)视觉
- 前端总结·基础篇·CSS(三)补充
- 前端总结·基础篇·JS(一)原型、原型链、构造函数和字符串(String)
- 前端总结·基础篇·JS(二)数组深拷贝、去重以及字符串反序和数组(Array)
- 前端总结·基础篇·JS(三)arguments、callee、call、apply、bind及函数封装和构造函数
- 前端总结·基础篇·JS(四)异步请求及跨域方案
- 前端总结·工具篇·管理(一)常用模块化方案
目录
一、函数使用
1.1 函数声明和函数表达式
1.2 函数封装(自调用函数、闭包)
1.3 函数属性(arguments、callee)
1.4 构造函数
二、函数技巧
2.1 改变函数作用域(call/apply/bind)
2.2 for循环中的setTimeout问题修复
一、函数使用
字符串和数组都是用来存储数据。需要做一些特定的事情的时候,我们就会会用函数封装起来。
1.1 函数声明和函数表达式
声明一个函数可以用函数声明或者函数表达式。
- 函数表达式必须先声明后调用
- 函数内的变量需要使用var声明,否则会污染全局变量
function hello( name ) { some code ... } // 函数声明
var hello = function ( name ) { some code ... } // 函数表达式
// 变量提升 | 函数内部的变量未使用var声明,执行后会导致变量成为全局变量
var age = 22
function showAge(){
age = 23
console.log(age)
}
showAge() // 23 | 执行函数
console.log(age) // 23 | 测试全局变量age的值
1.2 函数封装(自调用函数、闭包)
实际项目中会引入很多外部JS文件,为了避免彼此命名冲突。通常各自都会对内部函数进行封装。(现在更好的方案是使用模块化,模块化以后再总结)
自调用函数
使用自调用函数,把整个JS文件的代码都封装在内。
- 这样做的好处是不会污染全局变量,可以很好的减少命名冲突。
- 最后把对外访问的接口挂载在window上。
(function(){
// some code ...
window.myApp = myApp() // 把对外访问的接口挂载在window上
})()
闭包封装
如果你内部使用的是函数表达式,并且不用var声明,变量依旧会泄露到全局。
// a.js
(function(){
function myApp() {
// 定义showName方法
function showName(name) {
console.log(name)
}
// 定义showAge方法
function showAge(age){
console.log(age)
}
// 返回一个对象
return {
showName: showName,
showAge: showAge
}
}
window.myApp = myApp()
})()
功能扩展
引入上面的a.js文件,并且创建b.js来写程序主逻辑。
- 你也可以写在一个文件,写在两个文件是为了把接口和控制器分开,方便管理。
- 你可以修改上面提供的方法,或者新添加一条方法。
//b.js
// 修改已有方法
myApp.showName = function (name) {
console.log('Call me '+name)
}
// 定义新方法
myApp.showCity = function (city) {
console.log(city)
}
myApp.showName('berg') // 能够访问 | berg
myApp.showCity('NanChang') // 能够访问 | NanChang
showName('berg') // 不能访问 | Uncaught ReferenceError: showName is not defined
1.3 函数属性(arguments、callee)
arguments是用来存放实参的,可以通过下标访问实参的值。callee指向当前执行的函数,可以在递归的时候用。具体递归场景以及代码,请见MDN。
- callee不能实现尾递归
- callee在ES5严格模式中禁止使用
- caller指向调用当前函数的函数(已废弃)
function show(name,age) {
console.log(name) // berg
console.log(age) // 22
console.log(arguments) // ["berg", 22]
console.log(arguments.callee) // function show(name,age) {}
}
show('berg',22)
1.4 构造函数
ES6可以使用Class实现继承,以后在单独总结ES6的时候会提到。推荐一个非常好的ES6系列教程,深入浅出ES6
// 声明构造函数 Human
function Human() {
this.play = function(){
console.log('I\'m playing.')
}
}
// 声明构造函数 Male
function Male() {
this.sex = 'male'
}
// 声明构造函数 Female
function Female() {
this.sex = 'female'
}
// 让Male和Female继承Human
Male.prototype = new Human()
Female.prototype = new Human()
// 创建xiaoming对象并且测试继承结果
var xiaoming = new Male()
console.log(xiaoming.sex) // male
console.log(xiaoming.play()) // I'm playing.
// 创建xiaohong对象并且测试继承结果
var xiaohong = new Female()
console.log(xiaohong.sex) // female
console.log(xiaohong.play()) // I'm playing.
二、函数技巧
2.1 改变函数作用域(call/apply/bind)
当需要改变上下文的this的时候,可以使用call/apply/bind。(更详细的解释请见ChokCoco,需要用call实现继承请见MDN)
- 三种方法的第一个参数都是this的上下文
- apply第二个参数是数组,call和bind后面都是接单个参数
- call和apply默认会自动执行,bind需要在后面加()来自动执行
- bind是ES5语法,支持IE9+
/* 以下以数组合并为例子
* 使用不同的方法之前,请确保a和b为默认值
*/
var a = [1,2,3] // 测试用的默认值
var b = [4,5,6] // 测试用的默认值
a.push(b) // 直接使用push(不符合预期)
console.log(a) // [1, 2, 3, Array[3]]
// call方法(在这种情况下要逐个输入参数,不太方便)
Array.prototype.push.call(a,4,5,6)
console.log(a) // [1, 2, 3, 4, 5, 6]
// apply方法(第二个参数直接传入数组,非常适用这种场景)
Array.prototype.push.apply(a,b)
console.log(a) // [1, 2, 3, 4, 5, 6]
// bind方法
Array.prototype.push.bind(a,4,5,6)() // 注意看,这里需要加一个自动执行函数
console.log(a) // [1, 2, 3, 4, 5, 6]
2.2 for循环中的setTimeout问题修复
setTimeout有自己的this。如果在外层放一个for循环,意味着会一次性执行完,而没有起到延时的作用。解决方案是使用闭包。此处主要参考JavaScript 秘密花园
- setTimeout是一个定时执行函数。接受两个参数,第一个是执行的函数,第二个是延迟执行的时间。通常用在登陆之后,提示几秒钟之后跳转到首页(现在基本不这样做了)。
- setInterval和setTimeout基本一致。只是第二个时间参数,表示的是每多长事件执行一次。
- 第二个参数的时间单位是毫秒(1000表示为1秒)
// 使用闭包前
for(var x = 0; x<10; x++) {
setTimeout(run,1000) // 10
}
function run() {
console.log(x)
}
// 使用闭包后
for(var x = 0; x<10; x++) {
setTimeout((function (x) {
return function() {
console.log(x) // 0 1 2 3 4 5 6 7 8 9
}
})(x),1000)
}
总结
全文主要参考以下网站
推荐的教程
- JavaScript系列 @ 廖雪峰
- JavaScript 标准参考教程(alpha) @ 阮一峰
- 深入理解JavaScript @ 汤姆大叔
- 深入浅出ES6
- ECMAScript 6 入门 @ 阮一峰
- 张鑫旭博客
全文主要是参考MDN写出的总结。外加ChokCoco和JavaScript 秘密花园中的细致分析,以及自己平时的一些总结写成此文。
文中的错误还望能够指出,会及时做出修改(哪怕是错别字)。Vue的基本理念现在差不多搞清楚了,大概在下周,会对Vue做一个总结(其实官方文档是最好的总结 _)。
前端总结·基础篇·JS(三)arguments、callee、call、apply、bind及函数封装和构造函数的更多相关文章
- 前端总结·基础篇·JS(一)五大数据类型之字符串(String)
前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(二)补充 前端总结·基础篇·JS(一)五大数据类型之字符串(String) 目录 这是& ...
- 前端总结·基础篇·JS(二)数组深拷贝、去重以及字符串反序和数组(Array)
目录 这是<前端总结·基础篇·JS>系列的第二篇,主要总结一下JS数组的使用.技巧以及常用方法. 一.数组使用 1.1 定义数组 1.2 使用数组 1.3 类型检测 二.常用技巧 2.1 ...
- 前端总结·基础篇·JS(四)异步请求及跨域方案
前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·JS(一)原型.原型链.构造函数和字符串(String) 前 ...
- 前端总结·基础篇·JS(一)原型、原型链、构造函数和字符串(String)
前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·JS(一)原型.原型链.构造函数和字符串(String) 前 ...
- js 中arguments,call,apply,bind的使用
//对于 arguments和this, 每个函数都有自己独有的arguments和this, 且不进行链式查找 //arguments是什么? //答:1:arguments是收到的实参副本 //2 ...
- 前端总结·基础篇·CSS(三)补充
前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 目录 一.移动端 1.1 视口(viewport) 1.2 媒体查询(medi ...
- 前端总结·基础篇·CSS(一)布局
目录 这是<前端总结·基础篇·CSS>系列的第一篇,主要总结一下布局的基础知识. 一.显示(display) 1.1 盒模型(box-model) 1.2 行内元素(inline) &am ...
- 前端总结·基础篇·CSS(二)视觉
前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·CSS(四)兼容 目录 一.动画(animation)(IE ...
- 前端总结·基础篇·CSS
前端总结·基础篇·CSS 1 常用重置+重置插件(Normalize.css,IE8+) * {box-sizing:border-box;} /* IE8+ */body {margin:0;} ...
随机推荐
- (二)Lua脚本语言入门
上一篇文章忘了插入代码了,方便粘贴复制...... 函数 对于c语言就是 void aa()//c语言是用void { print("这是一个函数") } Lua就变成了 func ...
- db2_errroecode
sqlcode sqlstate 说明 000 00000 SQL语句成功完成 01xxx SQL语句成功完成,但是有警告 +012 01545 未限定的列名被解释为一个有相互关系的引用 +09 ...
- 一篇文章搞定css3 3d效果
css3 3d学习心得 卡片反转 魔方 banner图 首先我们要学习好css3 3d一定要有一定的立体感 通过这个图片应该清楚的了解到了x轴 y轴 z轴是什么概念了. 首先先给大家看一个小例子: 卡 ...
- ABP框架 - 嵌入资源
文档目录 本节内容: 简介 创建嵌入文件 xproj/project.json 格式 csproj 格式 添加到嵌入式资源管理器 使用嵌入式视图 使用嵌入式资源 ASP.NET Core 配置 忽略文 ...
- 初学NodeJs
1.在ecmascript部分node和js其实是一样的,比如数据类型的定义,语法结构,内置对象 在js中的顶层对象 window 在node中的顶层对象 global 注意:在node中也没有什么w ...
- 关于最优化读写,测试各个加锁:Lock、安全字典、信号量、ReaderWriterLock、ReaderWriterLockSlim
大家对于自身项目中都有本地缓存的逻辑,但这块的读写何种机制下哪个快,哪个慢,需要测试对比,以下测试报告,期望给大家一个借鉴,如果有更好的测试结果也欢迎大家一起讨论. 以下测试是开启10个并发任务对同一 ...
- Linux实战教学笔记14:用户管理初级(下)
第十四节 用户管理初级(下) 标签(空格分隔): Linux实战教学笔记-陈思齐 ---更多资料点我查看 1,用户查询相关命令id,finger,users,w,who,last,lastlog,gr ...
- 《汇编语言程序设计》——仿windows计算器
<汇编语言程序设计> ——计算器程序设计 目录 一. 题目与目标 1. 题目 2. 学习目的 二. 分析与设计 1. 系统分析 2. ...
- Android开发8:数据存储(二)——SQLite数据库和ContentProvider的使用
前言 啦啦啦各位小伙伴们许久不见了~学期末和过年期间自己忙着做其他事没能及时更新Android开发系列课程的博客,实在是罪过罪过~ 好啦~废话不多说,进入我们今天的主题.今天我们将和大家学习其他的数据 ...
- 常用php时间函数用法汇总
1.设置时区的方法: php5后都要自己设置时区,要么修改php.ini的设置,要么在代码里修改. 在PHP.INI中设置时区 date.timezone = PRC 在代码中设置时区 1 date_ ...