javaStript中的 函数调用形式主要有四种
一、函数调用形式
第一种定义函数
//1.函数调用形式
function function_name (argument) {
console.log("this is a function");
console.log(this);//this is a window
}
function_name();
//window.function_name();这种调用类似的吧
第二种匿名函数
//使用函数的Lambda表达式定义函数,然后调用
var function_name = function() {
console.log("this is a function");
console.log(this);//this is a window
};
function_name();
如上两种所示,当前的执行环境都是window,直接的去调用
二、对象方法调用形式
函数调用模式很简单,是最基本的调用方式。
但是同样的是函数,将其赋值给一个对象的成员以后,就不一样了.
将函数赋值给对象的成员后,那么这个就不在称为函数,而应该叫做方法.
其可以看做为当前对象的方法,如果当前对象是类(可以看作为静态方法,我的理解)
var function_name = function(){
console.log('this is a function');
console.log(this);
// this is a object (objectName)
//this is changed by this context(根据执行的环境而改变)
//果果直接调用就是window对象,复值给某个对象之后,就是当前对象
}
var objectName = {};//this is a object
objectName.fn = function_name;
objectName.fn();// this is a function
类似的情况,和上面的差不多
//下面这种写法,相当于向创建一个空的对象,然后赋值一个方法
//就是对象调用方法
var function_name ={
fn:function(){
console.log('this is a function');
console.log(this);//this is a object
}
}
function_name.fn();
三、构造调用形式
同样是函数,在单纯的函数模式下,this 表示 window。
在对象方法模式下,this 指的是当前对象。
除了这两种情况,JavaScript 中函数还可以是构造器
将函数作为构造器来使用的语法就是在函数调用前面加上一个 new 关键字。
var Person = function(){
this.name ="wangji";
this.age=24;
this.sayMyNameAndAge = function(){
console.log(""+this.age+this.name);
}
console.log(this);//this is Person object
}
var person = new Person();
person.sayMyNameAndAge();
这里的this指向对象本身
所有需要由对象使用的属性,必须使用 this 引导。
函数的 return 语句意义被改写,如果返回非对象,就返回this。
分析创建的过程
- 首先定义了函数Person,当程序执行到这里时不会执行函数体,因此 JavaScript 的解释器并不知道这个函数的内容。
- 接下来执行new关键字,创建对象,解释器开辟内存,得到对象的引用,将新对象的引用交给函数
- 紧接着执行函数,将传过来的对象引用交给this。也就是说,在构造方法中,this 就是刚刚被 new 创建出来的对象。
- 然后为 this 添加成员,也就是为对象添加成员。
- 最后函数结束,返回 this,将 this 交给左边的变量。
分析过构造函数的执行以后,可以得到,构造函数中的 this 就是当前对象。
构造器中的 return
- 在构造函数中 return 的意义发生了变化。
- 首先如果在构造函数中,如果返回的是一个对象,那么就保留原意。
- 如果返回的是非对象比如数字、布尔和字符串。那么就返回this。
- 如果没有 return 语句,那么也返回 this。
例子:返回新的对象
var Channge = function() {
this.name = "汪吉";
this.age = 25;
return {
name:"王老吉",
age:24
};
};
//如果返回的是对象,那么就是新的对象啦,以前的没得关系啦!
var wangji = new Channge();
console.log(wangji.name);//王老吉
console.log(wangji.age);//24
例子:返回其他或者不返回
var Channge = function() {
this.name = "汪吉";
this.age = 25;
return "wangji";//其他或者不返回
// return 语句无效
};
//如果返回的是其他(或者不返回),那么就是当前对象啦
//自己在chrome 控制台试试
var wangji = new Channge();
console.log(wangji.name);//汪吉
console.log(wangji.age);//25
四、apply and call
除了上述三种调用模式以外,函数作为对象还有 apply 方法与 call 方法可以使用,这便是第四种调用模式。
因为函数本身就是对象拥有自己的方法。
例子1:XXX.apply(null) 无参数
var funcTest1 = function() {
this.name = "wangji";
alert(this);//当前为window
};
//XXX.aply("上下文",[参数数组]);
//这里传null代表为全局的window
funcTest1.apply(null);
alert(name);
例子2:传入新创建的对象
var funcTest2 = function() {
this.name = "wangji";
alert(this);//当前上下文(object)
};
//XXX.aply("上下文",[参数数组]);
//这里传null代表为全局的window
//这里传入objectName对象,改变funcTest2的执行上下文
//所以funcTest2中的上下文为当前objectName
//所以objectName能够调用之前funcTest2拥有的对象的方法。
var objectName = {};
funcTest2.apply(objectName);
alert(objectName.name);
apply 和call相同,只是call调用(上下文,参数…);
JQuery中刚刚开始的时候有很多的变量,代表相应的函数,就是如下这样调用的。
var arr = [];
var push = arr.push;
//这里arryTest使用了arr中的push函数
var arryTest = [];
push.call(arryTest,[1,2,3,4,5]);
console.log(arryTest);//1,2,3,4,5
五、为什么这么使用 ?存在call和apply的原因
在javascript OOP中,定义一个类.
主要的目的就是为了重用,修改了当前的执行环境而已。
function Cat(){
};
Cat.prototype ={
food:"fish",
say:function(){
console.log("I Love food is :",this.food);
}
}
var cat = new Cat();
console.log(cat.say());
//dog想重新利用say方法
var dog = {food:"bone"};
cat.say.call(dog);//I Love food is:bone
但是如果我们有一个对象 var dog = {food:”bone”},我们不想对它重新定义say方法,
那么我们可以通过call或apply用cat的say方法:cat.say.call(whiteDog);
所以,可以看出call和apply是为了动态改变this而出现的,当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作。
用的比较多的,通过document.getElementsByTagName选择的dom
节点是一种类似array的array。
它不能应用Array下的push,pop等方法。
我们可以通过:
var domNodes = Array.prototype.slice.call(document.getElementsByTagName(“*”));
这样domNodes就可以应用Array下的所有方法了。