函数有四种形态
-> 函数形态
-> 方法形态
-> 构造器形态
-> 上下文形态(call, apply)
函数的四种调用模式
所有的 this 都是由当前函数决定,最终都是由函数的四种调用模式决定的。
①
函数调用模式,只会执行一段代码,同时函数中的 this 是全局对象 window;返回值由return语句决定,如果没有return语句就表示没有返回值
function f1(){
console.log(this);
}
f1();//window
function f2(){
return function(){
console.log(this);
}
}
var f2n=f2();
f2n();//this——>window,这也是一次函数调用模式
function f3(){
f3n();//函数调用模式——————>window
function f3n(){
console.log(this);
}
}
f3();// window
②
方法调用模式,只会执行一段代码,同时方法中的 this 是方法的所有者,即当前的实例对象;返回值由 return 语句决定
//代码1:
var obj={
age:10,
say:function(){
console.log(this.age);
}
};
obj.say();//方法调用模式
//代码2:
function f1(){
console.log(this);
}
var obj2={
s1:f1//将f1函数赋值给obj2.s1属性
};
obj2.s1();//方法调用模式——>this:obj2
//代码3:
var obj3={
age:10,
s1:function(){
console.log(this.age);
}
};
var obj4={
age:20,
s2:obj3.s1//将obj3.s1函数赋值给s2属性
};
obj4.s2();//方法调用模式:this——>obj4
③
构造器调用模式,会用来创建一个对象,还是执行一段代码,this 表示当前对象
返回值:
a. 没有手动添加返回值,默认返回 this
b. 返回了一个基本数据类型(number / boolean / string / null / undefined),最终返回 this
c. 返回了一个复杂数据类型(对象),最终返回该对象
//代码1:
function Person(){
this.age=20;
this.name="张三";
console.log(this);
}
//构造函数调用模式:
var p1=new Person();
//代码2;
function P2(){
this.age=18;
return "abc";
}
var p2=new P2();//p2.age=18
//代码3:
function P3(){
this.age=10;
return {};
}
var p3=new P3();//p3.age:undefined
console.log("p3.age");
console.log(p3.age);
//代码4:
function P4(){
this.age=10;
return [1,3,5];
}
var p4=new P4();//p4.age:undefined
console.log("p4.age");
console.log(p4.age);
④
上下文调用模式,可以用参数来控制 this 的含义
语法:
函数.call(对象,参数列表)
函数.apply(对象,参数数组)
call 和 apply 除了参数不同,功能完全相同
this :
a. 传递一个 null / undefined ,this 指向 window
b. 传递一个 数字 / 字符串 / 布尔值,this 指向 对应的基本包装类型的对象(Number / String / Boolean)
c. 传递一个 对象:this 指向该对象
返回值:由 return 语句决定
例如调用 函数 func 需要两个参数
func( 1, 2 )
那么使用上下文调用的语法是
func.call(obj, 1, 2);
func.apply(obj, [1, 2]);
apply 方法就是为了处理伪数组
借用函数调用
p.sayHello => p.sayHello.call(p) p.sayHello.apply(p)
function f1(){
console.log(this);
}
//上下文模式
f1.call(null);//window
f1.call(undefined);//window
f1.call(1);//Number的实例
f1.call("abc");//String的实例
f1.call(true);//Boolean的实例
var s1="abc";
console.log(s1.length);//3
console.log(s1[0]);//"a"
//代码内部创建了字符串所对应的String构造函数的实例
//{0:"a",1:"b",2:"c",length:3}
//代码执行完毕之后,就会把这个实例给销毁
练习题1:
function f1(){
this.length=5;
return function(a,b,c){
this.length=10;
return [1,3,5];
}
}
//构造函数调用模式:
var r1=new f1();//r1是函数
console.log(r1.length);//任何函数都有一个length属性表示形参的个数:3
//函数调用模式
var r2=r1();//r2:[1,3,5]
console.log(r2.length);//3
//构造函数调用模式
var r3=new r1();//r3:[1,3,5]
console.log(r3.length);//3
练习题2:
var length = 10;
function fn() {
console.log(this.length);
}
var obj = {
length: 5,
method: function (f) {
f();//f变量的值是fn函数,但是这里是函数调用模式--->this:window————>window.length:10
arguments[0]();//方法调用模式,this:arguments——>arguments.length:2
}
}
obj.method(fn, 1);
var o1={
0:function(){
},
say:function(){
}
};
o1[0]();
//o1.0();//错误
o1.say();
o1["say"]();