函数的定义
// 1.函数定义的方式:函数的声明
//fun就是标识符
function fun() {
console.log(1)
}
fun()
// 2.函数定义的方式:函数表达式
var fn = function() {
console.log(2)
}
fn()
// 3.函数声明的提升
fun()
function fun() {
console.log(3)
}
// 4.函数表达式不可以提升
fn() //fn is not a function
var fn = function() {
console.log(fn)
}
函数定义的new的方式
通过构造函数定义一个函数,函数本身也是一个对象
// 本节技术了解即可
// 通过构造函数定义一个函数,函数本身也是一个对象
// var fun = new Function('a','b','var a = "1";console.log(a+b)')
var fun = function (a,b){
var a = "1"
console.log(a+b) // console.log("1" + 3) => console.log("1" + "3") => "13"
}
fun(2,3)
函数的调用
判断函数内部的this是指向谁?
函数被谁调用,那么这个函数内部的this就指向谁
1、普通函数的调用
通过给函数名称(标识符)或者变量名添加()执行
内部有个this对象,默认指向window
function fun() {
console.log(1)
console.log(this)
}
fun()
2、构造函数
通过new关键字进行调用,构造函数内部的this指向的是创建的实例对象
如果是通过普通函数的方式调用,内部的this指向Window类型的对象
function Person(name) {
this.myName = name
console.log(this) // p1
}
// var p1 = new Person("zhangsan")
Person("zs")
3、对象中的方法
对象中的方法的this默认指向的是调用这个方法的对象
function fun() {
console.log(1)
console.log(this)
}
var obj = {
sayHi: function() {
console.log(this)
console.log('hahah')
},
fn: fun
}
obj.sayHi()
// 判断一个函数内部this的指向的时候,要联系执行上下文,在调用的时候,分析他们之间的关系,看按照什么方式调用
obj.fn()
4、事件处理函数
在事件被触发之后,会自动执行函数
事件函数内部this指向的是 事件源
// 需求:点击网页,产生一个事件。输出一句话
// document.onclick = function (){
// console.dir(this)
// }
5、回调函数中this
定时器和延时器中的回调函数的this
window.setTimeout(function() {
console.log(this) //window
}, 1000)
call、bind、apply方法
1、call方法
1.1功能:第一个可以改变函数内部的this指向;
第二个是可以执行函数并传参
1.2参数:第一个参数,this要指向的对象;
第二个参数就是要传递给调用call方法的函数的参数
1.3返回值:就是调用call方法的函数的返回值
var obj = {
myName: 'zhangsan'
}
var res = fun.call(obj, 3, 5)
console.log('res:', res)
call方法的运用
构造函数中扩展原型方法(原型对象上的方法就是原型方法)
给Array构造函数添加计算数组的元素的和的方法
Array.prototype.getSum = function() {
}
1、 需求: 求[1, 2, 3, 4, 5, 6, 7, 8] 的所有元素的和
var arr = [1, 2, 3, 4, 5, 6, 7, 8]
Array.prototype.getSum = function() {
// console.log(this)
const res = this.reduce((curr, pre) => {
return curr + pre
}, 0)
console.log(res)
}
var sum = arr.getSum()
console.log(sum)
2、 伪数组
var obj = {
0: 10,
1: 20,
2: 30,
length: 3
}
Array.prototype.push.call(obj, 50)
2、apply方法
2.1功能:第一个可以改变函数内部的this指向;
第二个是可以执行函数并传参
2.2参数:第一个参数,this要指向的对象;
第二个参数就是要传递给调用call方法的函数的参数,但是一个有参数组成的数组
2.3返回值:就是调用call方法的函数的返回值
var obj = {
myName: 'zhangsan'
}
var res = fun.apply(obj, [3, 5])
console.log('res:', res)
apply方法的运用
需求:求一个数组中的最大元素值
var max = 0
var arr = [1, 2, 3, 4, 5, 6]
for (var i = 0; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i]
}
}
var arr = [2, 1, 6, 8, 1, 5]
Math.max.apply(Math, arr)
需求:输出一个数组中的所有元素或者展开一个数组或者提取个数组
console.log.apply(console, arr)
需求:返回一个数组中的最大值和最小值的和并且输出
var arr = [2, 1, 6, 8, 1, 5]
// 需求最好用函数
function MaxMin() {
var x = Math.max.apply(Math, arr)
var y = Math.min.apply(Math, arr)
console.log(x + y)
return (x + y)
}
MaxMin()
3、bind方法
3.1功能:第一个可以改变函数内部的this指向;注意:它不能执行函数!!!!!!!!!
3.2参数:第一个参数,this要指向的对象;第二个参数就是要传递给调用call方法的函数的参数
3.3返回值:返回一个新的函数,这个函数的this就指向了参数指定的对象
var obj = {
myName: 'zhangsan'
}
function fun(a, b, c, d) {
console.log(this)
console.log(a + b + c + d)
return a + b + c + d
}
var fn = fun.bind(obj, 1, 2, 3, 4)
var res = fn()
console.log('res:', res)
bind方法的运用
改变定时器内部的函数的this指向
var obj = {
myName: 'zs',
age: 19,
s: function() {
// 每隔1秒循环定时打印这个对象的年龄
setInterval(function() {
console.log(this.age)
}.bind(this), 1000)
}
}
obj.s()
改变事件函数中的this
让this指向指定的对象
var o = {
}
document.onclick = function() {
console.log(this)
}.bind(o)
函数的其他成员
输出函数,观察内部成员
function fun() {
console.log(1)
}
console.dir(fun)
function fn(a, b) {
// arguments
// 获取函数实参的所有值
// console.log(fn.arguments)
// console.log(arguments)
// 获取实参个数
console.log(fn.length)
// 获取函数名字
console.log(fn.name)
}
fn(1, 2, 3, 4, 5, 6, 7, 8)
需求:求一个数据列表中的元素的最大值
可以接受不定个数的参数,并求这些参数的最大值
function max() {
// 1、获取到列表中的所有数据
const arr = arguments
var max = arr[0]
for (var i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i]
}
}
return max
}
var m1 = max(2, 3, 5, 6)
var m2 = max(3, 5, 2, 9, 1, 2, 5, 7)
console.log(m1)
高阶函数
1、函数作为另一个函数的参数
function eat(fn) {
fn()
}
eat(function() {
console.log('看电影')
})
2、函数作为一个函数的返回值
// 实现 一个函数可以输出1000+m,10000+m,1000000+m
function outer(n) {
return function inner(m) {
console.log(m + n)
}
}
var fun = outer(1)
console.log(fun)
fun(7)
fun(9)
fun(10)
闭包
1.闭包的定义
在一个外部函数内部定义内部函数,在内部函数中调用了外部的函数定义的变量,并且在外部函数返回内部函数
在一个内部函数内部拿到外部函数中的变量,然后在外部函数外部可以访问到外部函数中的变量
function outer(){
var a = 10
function inner(){
// console.log(a)
return a
}
// 注意:返回的是函数,不是函数的调用
return inner
}
// 由于函数作用域的原因,在函数外部是无法访问到函数内部定义的变量的
// console.log(a) //Uncaught ReferenceError: a is not defined
var fun = outer()
var res = fun()
console.log(res)
闭包的用途场景
1、类似于缓存的作用
function outer() {
var a = 10
function inner() {
// console.log(a)
a++
return a
}
// 注意:返回的是函数,不是函数的调用
return inner
}
// 由于函数作用域的原因,在函数外部是无法访问到函数内部定义的变量的
// console.log(a) //Uncaught ReferenceError: a is not defined
var inner = outer()
var res = inner()
console.log(res)
var res1 = inner()
console.log(res1)
2、解决循环过程中函数赋值的问题
var arr = []
for (var i = 0; i < 3; i++) {
// ()() 立即执行函数IIEF
(function(i) {
arr[i] = function() {
console.log(i)
}
})(i)
}
arr[0]() // 0
arr[1]() // 1
arr[2]() // 2