/**
* js 里函数调用有 4 种模式:方法调用、正常函数调用、构造器函数调用、apply/call 调用。
*/
//方法调用:
var a = {
v:5,
func : function(value){
this.v = value;
console.log("这是一个方法调用:a.v == " + this.v);
}
//这个时候,上面函数里的 this 就绑定的是这个对象 a。所以 this.v 可以取到对象 a 的属性 v。
}
a.func(5);
console.log("这个时候,上面函数里的 this 就绑定的是这个对象 a。所以 this.v 可以取到对象 a 的属性 v。");
//正常的函数调用:
function f(value){
this.x = value;
console.log("这是一个正常的函数调用:this.x == " + this.x + "this 是调用对象,也就是绑定的windows");
//这个时候,函数 f 里的 this 绑定的是全局对象,如果是在浏览器运行的解释器中,一般来说是 window 对象。所以这里 this.x 访问的其实是 window.x ,当然,如果 window 没有 x 属性,那么你这么一写,按照 js 的坑爹语法,就是给 window 对象添加了一个 x 属性,同时赋值。
}
f(6);
//构造器函数调用:
let handler = function(app){
this.app = app;
console.log("this.app=%o", app);
console.log("this=%o", this);
console.log("this.prototype=%o", this.prototype);
console.log("这是一个构造器函数调用 this.app.name = " + this.app.name + "this 是调用对象,也就是绑定的new出来的Handler对象本身");
}
let app = {
name:"lxkTest",
age: 25
}
let Handler = new handler(app);
//如果你在一个函数前面带上 new 关键字来调用,那么 js 会创建一个 prototype 属性是此函数的一个新对象,同时在调用这个函数的时候,把 this 绑定到这个新对象上。
//上面这个函数和正常调用的函数写法上没什么区别,只不过在调用的时候函数名前面加了关键字 new罢了,这么一来,this 绑定的就不再是前面讲到的全局对象了,而是这里说的创建的新对象,所以说这种方式其实很危险,因为光看函数,你不会知道这个函数到底是准备拿来当构造函数用的,还是一般函数用的。
//apply/call 调用:
//上面的 3 种函数调用方式,你可以看到,this 都是自动绑定的
console.log("call() 方法和 apply() 方法很类似,它们的存在都是为了改变 this 的绑定");
function handlerAbc(app1, app2){
console.log("this=%o" ,this)
this.app1 = app1;
this.app2 = app2;
}
var o = {};
handlerAbc.apply(o, [5]); //第一个参数是绑定给 this 的值,后面接受的是一个数组.
handlerAbc.call(o,66,88); //第一个参数也是绑定给 this 的值,但是后面接受的是不定参数,而不再是一个数组,也就是说你可以像平时给函数传参那样把这些参数一个一个传递。
//是不是很神奇,函数 handlerAbc 居然可以给 o 加属性值。当然,如果你 apply 的第一个参数传递 null,那么在函数 handlerAbc 里面 this 指针依然会绑定全局对象。
console.log(handlerAbc.app1 + " --- " + handlerAbc.app1); // undefined
console.log(o.app1 + " --- " + o.app2); // 5
console.log("上面讲的无论是 call() 也好, apply() 也好,都是立马就调用了对应的函数,而 bind() 不会");
//再来说 bind() 函数,上面讲的无论是 call() 也好, apply() 也好,都是立马就调用了对应的函数,而 bind() 不会,
//bind() 会生成一个新的函数,bind() 函数的参数跟 call() 一致,第一个参数也是绑定 this 的值,后面接受传递给函数的不定参数。
//bind() 生成的新函数返回后,你想什么时候调就什么时候调,看下代码就明白了
var m = {
"x" : 1
};
function foo(y) {
console.log("y = " + y);
console.log(this.x + y);
console.log("this=%o" ,this);
}
foo.apply(m, [5]); //立即调用
foo.call(m, 5); //立即调用
var foo1 = foo.bind(m, 7); //不是立即调用,想什么时候调就什么时候调, 当调用foo的时候,this就是m, 在foo函数内当然可以对m进行各种操作,比如说赋值。
console.log("m.x = " + m.x);
foo1();
var sum = function(x, y){
return x+y;
}
//创建一个类似于sum的新函数,但this的值绑定到null
//并且第一个参数绑定到1, 这个新函数的期望只传入一个实参
var succ = sum.bind(null, 1);
console.log(succ(2)); //输出 3; x 绑定到1,并传入2作为实参
//另外一个做累计计算的函数
var sum2 = function(y ,z){
return this.x + y + z;
}
//绑定this 和 y
var bindSum2 = sum2.bind({x : 1}, 2);
console.log(bindSum2(3)); //输出 6; this.x 绑定到1,y绑定到2, z 绑定到3
---------------------
作者:Tim猫
来源:CSDN
原文:https://blog.csdn.net/zhou_xtao/article/details/17581743
版权声明:本文为博主原创文章,转载请附上博文链接!