bind、call、apply方法:修改函数中this指向的
// 默认情况下在全局作用域内调用函数,this都是window
function test() {
console.log(this);
}
test();
// 输出结果为window
// 上面代码可以写成以下代码
function test() {
console.log(this);
}
window.test();
// 输出结果为window
bind方法
// bind方法
// 通过bind方法修改函数this的指向,并且会返回一个修改之后的新函数
var obj = {
name: "zs"
}
function test() {
console.log(this);
}
var fn = test.bind(obj);
test();
// 输出结果window
fn();
// 输出结果 {name: "zs"}
// 证明返回的新函数其中this就是obj
// 通过bind方法修改this指向,需要手动的调用返回出来的新函数
/*另外bind方法可以修改this之外,还可以传递参数,
只不过参数要写在this对象的后面用逗号隔开*/
var obj = {
name: "zs"
}
function test(num1, num2) {
console.log(num1, num2);
console.log(this);
}
var fn = test.bind(obj, 10, 20);
fn();
// 输出的结果 10 20
// 输出结果 {name: "zs"}
// 参数也可以在返回的新的函数进行传递
var obj = {
name: "zs"
}
function test(num1, num2) {
console.log(num1, num2);
console.log(this);
}
var fn = test.bind(obj);
fn(10, 20);
// 输出的结果 10 20
// 输出结果 {name: "zs"}
call方法
// call方法
/*修改this的指向,并立即调用原本的函数,它并不会生成新的函数,
call方法也可以传递参数,只不过参数要写在this对象的后面用逗号隔开*/
var obj = {
name: "zs"
}
function test(num1, num2) {
console.log(num1, num2);
console.log(this);
}
var result = test.call(obj, 30, 40);
console.log(result);
// 输出结果为undefined,说明call方法不会返回一个新函数
apply方法
// apply方法
/*修改this的指向,并立即调用原本的函数,它并不会生成新的函数
apply方法也可以传递参数,只不过参数要通过数组来传递参数*/
var obj = {
name: "zs"
}
function test(num1, num2) {
console.log(num1, num2);
console.log(this);
}
var result = test.apply(obj, [30, 40]);
console.log(result);
// 输出结果为undefined,说明apply方法不会返回一个新函数
bind、call、apply方法应用
/*以下有两个对象Person和Student,满足student是Person的一个子类的关系,
即学生也是一个人,也能使用人的属性和方法*/
// 定义一个Person的构造函数
function Person(name = "我是默认的名字", age = 0, gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.say = function () {
console.log(name + "跟你说'您好'");
}
}
// 定义一个Student的构造函数
function Student() {
/*如果我们想要使用人的属性和方法,而特意的在Studnt构造函数内部,
重复添加Person的属性和方法就会显得代码冗余*/
this.name = name;
this.age = age;
this.gender = gender;
this.say = function () {
console.log(name + "跟你说'您好'");
}
// 这是学生特有的方法
this.study = function () {
console.log(name + "是学生,要好好学习");
}
}
// 使用更改prototype属性更改Student原型对象为Person的实例对象
// 定义一个Person的构造函数
function Person(name = "我是默认的名字", age = 0, gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.say = function () {
console.log(name + "跟你说'您好'");
}
}
// 定义一个Student的构造函数
function Student() {
// 这是学生特有的方法
this.study = function () {
console.log(name + "是学生,要好好学习");
}
}
var myPerson = new Person("zs", 14, "man");
console.log(myPerson)
Student.prototype = new Person();
Student.prototype.constructor = Student;
var myStudent = new Student();
console.log(myStudent.name);
console.log(myStudent.age);
myStudent.say();
myStudent.study();
/*弊端
1.通过这种方式决定人的信息的实参,无论通过Student构造函数传递给Person构造函数
2.每次想要使用Person构造函数的属性和方法,都必须通过Person构造函数实例话对象,并传递该次人的信息的实参,如果只有一个人还好,但是如果多个人就会造成工作难度的提升*/
// 可以通过bind、call、apply关键字解决
// 定义一个Person的构造函数
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.say = function () {
console.log(name + "跟你说'您好'");
}
}
// 初次之外,我们还可以联动“对象四的”只是点,让Student构造函数的实例对象也能使用Person构造函数的公共方法
Person.prototype = {
constructor: Person,
cry: function () {
console.log(name + "正在哭");
}
}
// 定义一个Student的构造函数
function Student(name = "我是默认的名字", age = 0, gender, score) {
this.score = score;
// bind方法
// var result = Person.bind(this, name, age, gender);
// result();
// call方法
// Person.call(this, name, age, gender)
// apply方法
Person.apply(this,[name, age, gender])
// 这是学生特有的方法
this.study = function () {
console.log(name + "是学生,要好好学习");
}
}
Student.prototype = new Person();
Student.prototype.constructor = Student;
var myStudent = new Student("ls", 14, "man", 99);
console.log(myStudent.name);
console.log(myStudent.age);
console.log(myStudent.gender);
myStudent.say();
myStudent.study();
myStudent.cry();