相通点:都可以改变this 指向
为什么要改变this指向?
var name = "wx";
let obj = {
name: "abc",
say: function () {
console.log(this.name);
},
};
obj.say(); //显示abc
setTimeout(obj.say, 10); //显示wx
(实际我把var换成let或者const就不会打印出什么东西,因为那不再是全局变量,而是块级,输出一片空白捏)
同样调用obj,say,为什么结果不同呢?(涉及this绑定规则)
setTimeout所指向为window对象,其中的say方法是作为回调函数执行的,其中所传递的是函数的引用,并没有保留这个函数所属的对象,那么setTimeout调用函数时,其中的this取决于调用时的执行上下文(这里并没有指定上下文,所以10毫秒后在全局执行环境执行,浏览器自动绑定window。)
那么此时,如果想修改say方法中的this,就需要改变this指向了。
apply绑定this
setTimeout(function () {
obj.say.apply(obj);
}, 10); //输出abc
参数传递:参数是在调用新函数时传递给它的参数。
(将所有参数放到一个数组里去)
调用时立即执行方法
比如
let obj = {
name: "abc",
say: function (param1, param2) {
console.log(param1 + "," + param2 + "," + this.name);
},
};
setTimeout(function () {
obj.say.apply(obj, ["hello", "world"]);
}, 10);
call绑定this
跟apply差不多,唯一的区别是他需要的参数并非是一个数组,而是依次传入
调用时立即执行方法
所以需要注意与参数一一对应。
setTimeout(function () {
obj.say.call(obj, "hello", "world");
}, 10);
bind绑定this
与其他两者最大的区别是,bind返回值是一个新的函数
调用时不直接执行
let newFun = obj.say.bind(obj, "hello", "world");
newFun();
也不需要一次性传入所有参数
let newFun = obj.say.bind(obj);
newFun("hello", "world");
this的绑定规则
this和函数定义的位置没有关系,只和调用者有关系
在运行时被绑定
function foo() {
console.log(this);
}
foo(); //window
var obj = {
name: "wx",
foo: foo,
};
obj.foo(); // obj
foo.call("abc"); // string{ "abc" }
隐式绑定
1.通过对象调用函数绑定this
谁直接调用foo(),this就指向谁。
当然,这有个前置条件:对象所调用的函数必须是对象的属性。
function foo() {
console.log(this);
}
var obj = {
name: "wx",
foo: foo,
};
obj.foo();
显式绑定
如果obj对象上没有定义某个方法,但又想通过obj这个对象来调用这个方法?
也就是最上面的call,apply,bind了
new绑定this
function Student(name) {
console.log(this); // student {}
this.name = name;
}
var wx = new Student("abc");
console.log(wx); //student{name:'abc'}
涉及面试题:new 关键字创建一个新对象的步骤? 构造函数如何创建新对象?
1.创建一个空对象。
2.空对象的-proto-属性指向构造函数的Prototype属性。
3.执行构造函数,如果构造函数中有this,则此this指向刚刚创建的空对象。
4.返回刚刚创建的对象。
返回值?
在构造函数中,如果有return的话会返回什么?
function Student(name) {
console.log(this);
this.name = name;
return {
name: "我是对象",
};
}
var wx = new Student("abc");
console.log(wx); // {name:"我是新对象"}
如果return的是对象,则直接返回对象
如果return的是基本类型,则return语句无效,仍然返回刚刚创建的新对象。
如果多种绑定都存在,优先级?
隐式绑定和显式绑定同时存在,显式绑定优先级更高
new绑定优先级高于隐式绑定(隐式垫底了说是)
new绑定优先级高于bind
总结:new > 显式(bind)>隐式