函数的call方法, 可以指定this
函数的call方法, 可以在触发函数的同时替换其this指向
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// 函数call方法
// 函数默认情况下: 函数中this指向其所在的对象!
// 利用call可以强制修改 函数中this的指向!
var name = "全局区域";
var yanan = {
name: "亚楠",
intro: function () {
console.log(`${this.name} 是最棒的!`);
console.log("this:", this);
},
};
yanan.intro(); // 亚楠
// 函数是对象类型 -- 函数诞生 new Function()
// 对象类型是引用类型
var intro = yanan.intro;
intro(); // 全局区域
// 利用call强制替换函数 执行时 的 this
console.log("利用call 替换函数的this 然后执行");
intro.call(yanan);
intro.call({ name: "亮亮" });
// 伪代码: call实现了什么
// 相当于: intro.this = {name:"亮亮"}
// intro()
function demo() {
console.log("demo.this:", this);
}
// 执行时, 把demo中的this 替换成 参数1: yanan
demo.call(yanan);
</script>
</body>
</html>
call方法仿写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// call的使用场景:
// 函数.call(对象): 函数执行时就相当于是放在 参数对象 中执行
// 其中的this会指向 指定的对象
Function.prototype._call = function (obj) {
// 此处的this 就相当于是
// var demo = new Function("console.log(this.name)");
// fn是自定义的属性
obj.fn = this; //this是当前函数, 保存到了对象里
// 对象调用函数: 函数中的this指向其所在的对象!
obj.fn(); //函数的this 就变为了obj, 即传入的对象
};
// var demo = new Function('console.log(this.name)')
function demo() {
console.log(this.name);
}
var obj;
obj = { name: "亮亮" };
demo._call(obj);
demo._call({ name: "铭铭" });
</script>
</body>
</html>
<script>
Function.prototype._call = function (obj) {
// demo._call(obj): 所以_call函数中的this 就是demo
obj.fn = this;
obj.fn();
};
function demo() {
console.log(this.name);
}
var obj;
obj = { name: "亮亮" };
demo._call(obj);
function show() {
// 函数中的this指向函数执行时所在的对象
console.log(this.name);
}
var obj1 = { name: "亚楠" };
// 对象.属性名 = 值; 属性名不存在就会自动创建
obj1.fn = show;
console.log(obj1);
obj1.fn();
var obj1 = {
name: "亚楠",
// fn: function show() {
// console.log(this.name);
// },
};
obj1.fn = function show() {
console.log(this.name);
};
obj1.fn();
</script>
call使用场景
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// 用途: 当创建多个类似的构造函数时, 会有很多共同的属性, 可以提取这些共同的属性 组成一个 共享的构造函数
// 函数.call(新对象): 就会把函数的this替换成新对象, 然后触发函数
// 构造函数: 创建员工对象
function Employee(name, age, eid) {
this.name = name;
this.age = age;
this.eid = eid;
}
// 员工中细分为: 教师 管理者 ...
function Teacher(name, age, eid) {
// show(a,b,c); //调用时有三个参数
// 如果用call来修改this指向, 则写法为:
// show.call(新的对象, a,b,c)
// call(新的this, ...其他参数)
// 调用时 把Employee的this 换成当前的
// new Teacher() 得到的对象 -- 即 亚楠
// 所以内容生成的属性 都属于 当前的Teacher 对象
Employee.call(this, name, age, eid);
// this.name = name;
// this.age = age;
// this.eid = eid;
this.category = "教师"; //分类 = 教师
}
var yanan = new Teacher("亚楠", 19, "110011");
console.log(yanan);
// 员工=>管理者
function Manager(name, age, eid) {
// 利用员工函数 Employee 生成管理者的 其他通用属性
// 函数的形式: 对象.函数(); 函数的this就是其前面的对象
// 下方写法, 相当于是 window.Employee
// Employee(name, age, eid); //会导致函数内的this指向window
Employee.call(this, name, age, eid);
this.category = "管理者";
}
var m = new Manager("文华", 38, "100001");
console.log(m);
</script>
</body>
</html>
apply
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// 函数的apply: 同call, 都可以替换函数的this指向, 同时执行函数
// 同一个函数: show(a,b,c); 对象obj
// 用call书写: show.call(obj, a,b,c)
// 用apply书写: show.apply(obj, [a,b,c])
// 特点: apply(对象, [参数数组..])
let obj = { name: "楠楠" };
function show(a, b, c) {
console.log(this.name, a, b, c);
}
show.call(obj, 1, 2, 3);
show.apply(obj, [1, 2, 3]);
</script>
</body>
</html>
apply用途
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// apply的用途:
// Math的max()方法: 用来求出参数中的最大值
console.log(Math.max(12, 32, 435, 435, 34546));
// 求数组中的最大值
var nums = [123, 435, 34, 13, 435, 453, 213];
// max: 此方法只能判断 参数是数字的情况, 无法直接传递数组
console.log(Math.max(nums)); //NaN: not a numebr- 不是数字
// apply: 可以把数组类型 转化成 普通的函数参数结构
// 没有this指向的问题, 参数1不用传
var a = Math.max.apply(null, nums);
console.log(a);
// 合并数组:
var arr1 = [1, 2, 3, 4];
var arr2 = [11, 22, 33, 44];
// 回顾: 可以用concat合并
// var arr = arr1.concat(arr2);
// console.log(arr);
arr1.push(99, 88, 77, 66);
// apply: 参数arr1 必须要写, 代表执行 apply的对象
arr1.push.apply(arr1, arr2);
// ES6提供的语法糖, ... 可以拆解数组变为参数
arr1.push(...arr2);
console.log(arr1);
</script>
</body>
</html>
函数的bind方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// bind: 为函数绑定this, 返回绑定了this的新函数, 但是不立即执行
// 注意: bind不会修改原函数, 而是克隆一个新的出来, 把this替换了
var yanan = { name: "亚楠" };
var name = "全局";
function show() {
console.log(this.name);
}
//show1 是bind返回的新函数, 利用window方式查看, 可以发现这个函数带有一个 boundThis 属性, 其中就保存了 yanan 对象
// 正常函数: 本身不保存this指向, 会根据其运行所在的对象作为他的this
// 通过bind创建的函数, 带有 boundThis属性, 则调用时 就用把这个属性作为自己的this
var show1 = show.bind(yanan);
show1();
show();
</script>
</body>
</html>
bind的用途
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// bind的用途:
function Demo(count) {
this.count = count;
}
Demo.prototype._countdown = function () {
// 本质是 window.setInterval(): 所以此函数是在window对象中执行的
setInterval(function () {
// 此处的this就是window, 相当于是 widnow.count--
// 由于window中没有 count 变量, 所以出现 NaN
// 自增++ 自减-- a-- 相当于 a = a-1
console.log(this.count--);
}, 1000);
};
// d.countdown()
Demo.prototype.countdown = function () {
// 不要用默认的箭头函数, 此函数就是为了解决普通函数的bug而生的
// 利用bind方式, 把当前对象绑定给回调函数
var callback = function () {
console.log("this:", this);
console.log(this.count--);
};
// cb 变量, 存储了 绑定了 this 变量的 函数
var cb = callback.bind(this);
window.cb = cb;
setInterval(cb, 1000);
// setInterval(() => {
// console.log(this.count--);
// }, 1000);
};
var d = new Demo(1000);
d.countdown();
// 定时器: sti
// 参数1: 回调函数
// 参数2: 时间间隔, 单位ms 毫秒. 1秒=1000毫秒
// setInterval: 属于window的
// 所以函数中的this 就是window
// setInterval(function () {
// console.log("this:", this);
// console.log(new Date().toTimeString());
// }, 1000);
</script>
</body>
</html>