js函数详解

一、函数的命名

函数使用function关键字来定义。它可以用在函数定义表达式或者函数声明语句里。在这两种形式中,函数定义都从function关键字开始。
1.表达式

var a = function(){};//函数表达式实际上就是声明了一个变量,然后把一个函数的对象赋值给它

2.函数声明

function a(){};

区别:函数声明,会将声明提前,在还未执行的时候就会解析,这样如果一个作用域有两个相同的函数名,那么值就会被覆盖,保存的是最后的那个,但是函数表达式就不会这样,它会在代码执行的时候被解析。

二、函数调用的模式

1.方法调用模式

在JavaScript中函数也是一种对象,函数可以作为对象的属性,此时函数也称为对象的方法。

var object={
	op:1;
	oq:2;
	add:function(){
		this.sum = this.op+this.oq;//this指代当前对象
	}
}
onject.add();//作为方法调用,先调用方法,然后获取方法的值,执行object.rel;
object.rel;//结果是3

2.函数调用模式

function a(){};
a();//作为函数调用

**区别:**方法调用和函数调用的主要不同在于执行环境也就是上下文。

举例说明:

var o={    //对象o
    m:function(){    //对象中的方法m()
        var self=this;    //将this值保存至一个变量中
        console.log(this===o)    //true,this就是对象o
        f();    //调用嵌套函数f
 
        function f(){
            console.log(this===o);    //false:this指向的是全局对象或者undefined
            console.log(self===o);    //true:self指向外部函数的this值
        }
    }
}
//调用
o.m();

此处特别要注意嵌套函数里面的this不是指向外层函数的this,如果想访问外部的this,需要将它保存在变量self中(当然可以随便命名),这个变量和内部函数都在同一个作用域中。
注意
作为对象调用的时候this指向的是该对象;
作为函数调用的时候this指向的是全局变量,在浏览器中全局变量就是window,这里会隐式声明一个全局变量。

举例说明:

//这里写一个坐标平移的对象
var point = { 
x : 0, 							//两个属性
y : 0, 
moveTo : function(x, y) {         //函数作为对象的方法调用
    var moveX = function(x) {      // 内部函数,作为函数调用
    this.x = x;                   //this 绑定到了哪里?我们期望的是该对象的属性x
   }; 
   var moveY = function(y) {     // 内部函数
   this.y = y;                   //this 绑定到了哪里?
    }; 
   moveX(x);       			//调用(此处内部函数调用,隐式生成了一个全局变量x)
   moveY(y);     			//调用
   } 
}; 
point.moveTo(1, 1); 
point.x; //==>0 	 			 //原来对象的属性x和y并没有发生变化,说明之前的this指向的并不是外部的对象,而是全局变量
point.y; //==>0 
x; //==>1 
y; //==>1

针对这种情况,我们可以通过将外部this保存在一个变量中(因为在js中this是动态变化的)以下做出改进函数:

var point = { 
x : 0, 
y : 0, 
moveTo : function(x, y) { 
     var that = this; ///////////////////特别注意
    var moveX = function(x) { 
    that.x = x; //////////////////////////改变
    }; 
    var moveY = function(y) { 
    that.y = y; ///////////////////////////改变
    } 
    moveX(x); 
    moveY(y); 
    } 
}; 
point.moveTo(1, 1); 
point.x; //==>1 
point.y; //==>1

3.构造函数调用模式

如果函数或者方法前面带有关键字new,它就构成了构造函数调用,有个不成文的规定,构造函数的函数名首字母要大写。构造函数通常不使用return关键字,常用于初始化对象

function Point(x, y){ 
   this.x = x; 
   this.y = y; 
};
var point = new Point(1,2);//作为构造函数调用

凡是没有形参的构造函数都可以省略圆括号,如下是等价的:

var object = Object();
var object = Object;

4.apply或call调用模式

JavaScript中函数也是对象,这是js的特殊之处,那么我们知道对象有属性和方法,apply和call就是函数对象的方法。这两个方法允许切换函数执行的上下文环境(就是this绑定的对象),apply和call的功能相同,只是实现的时候call是将每个参数分别传入,而apply是将参数放进一个数组装入。

var func = function(arg1,arg2){   
};

//这里的this是自己想要指定的上下文,可以是js的任何一个对象,这样就能改变上下文了。

func.call(this,arg1,arg2);
func.apply(this,[arg1],[arg2]);

举例说明:

我们使用构造函数生成了一个对象 p1,该对象同时具有 moveTo 方法;使用对象字面量创建了另一个对象 p2,我们看到使用 apply 可以将 p1 的方法应用到 p2 上,这时候 this 也被绑定到对象 p2 上。另一个方法 call 也具备同样功能,不同的是最后的参数不是作为一个数组统一传入,而是分开传入的。

function Point(x,y){//构造函数
           this.x = x;
           this.y = y;
           this.moveTo = function(x,y){
               this.x = x;
               this.y = y;
           };
       };
        var p1 = new Point(2,3);//构造函数调用
        var p2 = {  //创建一个对象字面量
            x:0,//注意这里是逗号
            y:0;
        };
        p1.moveTo(1,1);//调用方法
        p1.moveTo.apply(p2,[5,4]);

下面这个更容易理解:

function hello(thing) {
  console.log(this + " says hello " + thing);
}

hello.call("Yehuda", "world") //=> Yehuda says hello world

猜你喜欢

转载自blog.csdn.net/weixin_43732570/article/details/84956033