JS相关知识学习笔记(三)
1、函数的定义
(1)命名函数
function fn() {}
(2)函数表达式(匿名函数)
var fun = function() {}
(3)new Function('参数1', '参数2', 函数体)
var f = function('a', 'b', 'console.log(a + b)')
f(1, 2) // 3
new Function()的参数必须都是字符串
所有的函数都是Function的实例(对象)
函数本质上也是对象
2、函数的调用方式以及this指向问题(一般都指向调用者)
(1)普通函数
function fn() {}
// 调用
fn() // this指向window
fn.call() // this指向window
(2)对象的方法
var o = {
say: function() {}
}
// 调用
o.say() // this指向o
(3)构造函数
function Person() {}
Person.prototype.say = function() {}
// 调用
var p = new Person() // 构造函数和原型对象中的this都指向p这个实例对象
(4)绑定事件函数(点击按钮即可调用)
btn.onclick = function() {
console.log(this) // this指向btn
}
(5)定时器函数(定时器隔特定时间自己调用)
setInterval(function() {
console.log(this) // this指向window
}, 1000)
(6)立即执行函数(自动调用)
(function() {
console.log(this) // this指向window
})()
3、修改函数内部的this指向
(1)call(this的指向, 参数1, 参数2, …)
可以调用函数传递参数,改变this的指向,也可以实现继承
var o = {name: 'zs'}
function sum(a, b) {
console.log(this) // this指向o对象
console.log(a + b) // 3
}
sum.call(o, 1, 2)
(2)apply(this的指向, [数组])
可以调用函数传递参数,改变this的指向,参数必须是数组,否则会报错
apply的主要应用:借助数学内置对象求最大值,使用时最好让apply的this指向Math
var o = {name: 'zs'}
function sum(arr) {
console.log(this) // this指向o对象
console.log(arr) // ls
}
sum.apply(o, ['ls'])
var arr = [23, 43, 51, 12, 26]
var max = Math.max.apply(Math, arr)
console.log(max) // 51
(3)bind(this的指向, 参数1, 参数2, …)
bind仅仅是返回一个新函数,把this指向修改为指定的对象,依次传递参数
原函数不会被更改
var o = {name: 'zs'}
function sum(a, b) {
console.log(this)
console.log(a + b)
}
var newF = sum.bind(o, 1, 2)
newF(3, 4) // 打印o 打印3 //按顺序传,传的1, 2——1+2=3
var newFn = sum.bind(o)
newFn(3, 4) //打印o 打印7 // 按顺序传,传的3, 4——3+4=7
var newFnn = sum.bind(o, 1)
newFnn(3, 4) //打印o 打印4 // 按顺序传,传的1, 3——1+3=4
var newFnnn = sum.bind(o, 1)
newFnnn() //打印o 打印NaN // 按顺序传,传的1——1+undefined=NaN
如果有的函数不需要立即调用,但是又想改变this的指向可以使用bind,比如改变定时器中的this指向
var btn = document.querySelector('button')
btn.onclick = function() {
this.disabled = true
setTimeout(function() {
this.disabled = false
}.bind(this), 3000)
}
bind进行函数参数的替换或者保存一些要使用到的值(下面要求弹出每一个li的索引值)
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
var lis = document.querySelectorAll('li')
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function(index) {
alert(index) // 直接弹出i则是for运行完最后的i
}.bind(lis[i], i) // 此处将函数的参数index替换为每一次循环的i,每点击一个li,弹出相对应的索引
}
</script>
如果不想改变函数内部的this指向,又想要在函数内部使用到外部的this,在不需要牺牲空间的情况下(即不需要使用全局变量that保存外部this了),可以使用bind将this指向设置为函数,将外部的this当作参数传递给函数
4、严格模式(ES5新增,IE10以下有兼容性问题,会忽略严格模式)
(1)为脚本开启严格模式
<script>
'use strict'
</script>
<script>
(function() {
'use strict'
})()
</script>
(2)为某个函数开启严格模式
<script>
function fn() {
'use strict' // 只为此函数开启严格模式
}
function f() {}
</script>
(3)严格模式的特点
1、变量必须先声明再使用,且随意删除已经声明好的变量
2、严格模式下的全局作用域中,this指向undefined,而不是window
3、严格模式下,构造函数不加new调用时,this会报错,实例化的构造函数还是指向创建的实例对象
4、定时器this指向的还是window
5、事件、对象的this还是指向调用者
6、函数的参数不可以同名
7、不可以在非函数代码块中定义函数(即:不可以在函数之外的{}中定义函数),比如:if,for等,函数中是可以嵌套函数的
5、高阶函数
-
高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出
// 函数作为参数,fun为高阶函数 function fun(callback) { callback && callback() } fun(function() {console.log(111)}) // 函数作为返回值,fn为高阶函数 function fn() { function f() {console.log(222)} return f } fn()
6、闭包
闭包:有权访问另一个函数作用域中变量的 函数或者代码使用方式(现象)
闭包的主要作用:延伸了变量的作用范围
function fn() {
var num = 10
return function(n) {
console.log(n + num)
}
}
var fun = fn()
fun(4) // 14 即4+10,访问到了num,产生了闭包fn(变量所在的函数)