01-定义函数的三种形式
<script>
// 1. 有名函数
fn1()
function fn1() {
console.log('我是有名函数')
}
// 特点:多次调用,可以先调用后定义(变量提升)
// 2. 匿名函数(函数表达式)
let fn2 = function () {
console.log('我是匿名函数')
}
// 变量名当名字(与有名唯一的区别:无法提升函数)
// console.log(fn1, fn2)
// 3. 函数虽然是我们自己写的:系统最终需要系统加工:系统都是通过Function函数(顶级构造函数)产生的
// 语法:new Function('参数1','参数2'...)
// 1. 所有参数:都必须加引号
// 2. 参数数量不确定
let fn3 = new Function()
// console.log(fn3)
let fn4 = function (a, b) {
return a + b
}
// 如果用Function实现
let fn5 = new Function('a', 'b', 'return a + b')
// Function对于参数的处理
// 最后一个实参:永远代表函数体
// 前面的实参:都是变量(形参变量)
console.log(fn4, fn5)
// 'a', 'b', 'return a + b',如何构造函数?
let fn6 = function (a, b) {
return a + b
}
// 如果想知道底层原理:eval():给字符串,能够解析成代码:eval()慎用,容易被攻击
// 结论
// 三种形式可以产生函数:有名、匿名、new Function()
// 所有的函数:最终都是由Function产生的(new Function())得到的
</script>
注意:
1.有名函数,特点:多次调用,可以先调用后定义(变量提升)
2.匿名函数(函数表达式),变量名当名字(与有名唯一的区别:无法提升函数)
3.如果用Function实现
// Function对于参数的处理
// 最后一个实参:永远代表函数体
// 前面的实参:都是变量(形参变量)
02-this与函数的四种模式-复习三种
<script>
// 1. 普通函数调用:定义函数,调用函数,this指向window:本质是window在调用
function fn1() {
console.log(this)
}
fn1() // window.fn1()
// 函数表达式也一样
let fn2 = function () {
console.log(this)
}
fn2()
// 目前为止:所有的回调函数,里面的this全部指向window
function fn3() {
console.log(this)
}
function callBack(fn) {
fn() // window.fn()
}
callBack(fn3)
// 2. 方法调用模式:方法就是定义在对象里面的函数(赋值给属性)
let obj = {
name: '张三',
say: function () {
console.log(this) // 指向obj
},
boyfriend: {
name: '男朋友',
say: function () {
console.log(this) // boyfriend
}
}
}
obj.say()
obj.boyfriend.say()
// 3. 构造函数调用模式:一定是new,new会产生对象,构造函数里面的this指向新产生的对象
function Student(name, age) {
this.name = name
this.age = age
console.log(this)
}
new Student('李四', 18)
new Student('王五', 19)
</script>
注意:
1.普通函数调用:定义函数,调用函数,this指向window:本质是window在调用
1.1.函数表达式也一样
2. 方法调用模式:方法就是定义在对象里面的函数(赋值给属性)
3. 构造函数调用模式:一定是new,new会产生对象,构造函数里面的this指向新产生的对象
03-this与函数的四种模式-借调模式(上下文模式)
<script>
// 1. 普通函数调用:定义函数,调用函数,this指向window:本质是window在调用
function fn1() {
console.log(this)
}
fn1() // window.fn1()
// 2. 方法调用模式:方法就是定义在对象里面的函数(赋值给属性)
let obj = {
name: '张三',
say: function () {
console.log(this) // 指向obj
},
boyfriend: {
name: '男朋友',
say: function () {
console.log(this) // boyfriend
}
}
}
obj.say()
// 借调本质:我想要做某个功能,但是发现已经有人做好了这个功能,但是功能是别人的:只能借
let newObj = { name: '小偷', skill: '偷东西' }
// 感受借调效果:call(借调函数)
fn1.call() // 借调成功:运行了:没有改变里面的this
fn1.call(newObj) // 借调成功:改变了主人:改变了里面的this
obj.say()
obj.say.call(newObj) // 只要是函数:一定可以借调
// 小结
// 1. 是函数一定可以借调
// 2. 借调的目的分良种
// 2.1 希望代码执行:借与不借没什么太大区别
// 2.2 改变函数里面的this指向
</script>
注意:
1. 普通函数调用:定义函数,调用函数,this指向window:本质是window在调用
2. 方法调用模式:方法就是定义在对象里面的函数(赋值给属性)
04-函数借调-call()
-apply()
-bind()
<script>
// 函数借调:修改内部的this,让代码按照自己的需求来实现相关的功能
// 借调有三种方式实现
/*
call、apply:这两种都属于一次性借调(多次使用,多次借调)
bind:绑定,可以重复使用
*/
// 富婆 重金求子
let richWoman = {
name: '前端',
getChild: function () {
console.log(this.name + '小白')
// console.log(this)
}
}
// 正常调用
richWoman.getChild()
// 后端 小白
// 借调(偷)
let ds = { name: '后端' }
// 借调语法
/*
函数.call(新对象)
函数.apply(新对象)
函数.bind(新对象)
*/
// call和apply都是一次性借调
richWoman.getChild.call(ds)
richWoman.getChild.apply(ds)
// 如果要多次使用:必须重新借调
richWoman.getChild() // 前端
richWoman.getChild.call(ds)
// bind:一次性绑定,可以多次调用:不是直接执行函数,而是返回一个新函数(this发生永久性的修改)
let newGetChild = richWoman.getChild.bind(ds)
console.log(newGetChild)
newGetChild()
newGetChild()
// 如果被借调的函数重新按照正常方式执行:都是原来的结果
richWoman.getChild()
// 扩展:bind如果只要借调一次,就不要保存到变量
richWoman.getChild.bind(ds)()
</script>
注意:
1.call和apply都是一次性借调
2.bind:一次性绑定,可以多次调用:不是直接执行函数,而是返回一个新函数(this发生永久性的修改)