重学js之函数的小秘密一

211 阅读4分钟

定义函数的4种方式

函数声明或者函数表达式
  • 函数声明

定义:强制以function开头,其后紧接着强制性的函数名以及括号和括号内一系列的可选参数,每个函数声明必须作为一个单独的javascript语句,函数声明必须独立(也能被包含在其他函数或者代码块中)

 函数字面量由四个部分组成
  + function关键字
  + 函数名字
  + 括号,括号里面装一个或者多个参数没有参数就是()
  + 函数体,包含在大括号内的一系列js语句,函数体可以为空但是必须存在
  • 函数表达式

定义:总是其他表达式的一部分函数(作为辅助表达式的右值,或者作为其他函数的参数)

//如
var fun = function(){};

function fun(callback){
   return callback()
}

setTimeout(function() {
    //....
}, 100);

函数声明与函数表达式的区别

1、解析器在执行环境中加载数据时,会优先读取函数声明,并使其在执行任何代码之前可用;而函数表达式,必须等到解析器执行到它所在的代码行,才会被解释执行如下:

fun()//杨紫1111
fun1()//fun1 is not a function
function fun(){
    console.log('杨紫1111')
}
var fun1 = function (){
    console.log('杨紫66')
};
//这涉及到变量提升后期专门一章讲解
构造函数
//num1,num2 是参数  最后一个参数都会被看成是一个函数体
new Function(num1,num2,"return num1+num2");

不推荐:会导致解析两次代码(第一次解析常规ECMAScript代码,第二次解析传入构造函数中的字符串)
箭头函数
箭头函数( (param1, param2,, paramN) => expression
生成器函数 MDN
function* 函数名(参数){函数体}

函数是第一型对象

  • 可以通过自面量进行创建
  • 可以赋值给变量、数组、或其他对象的属性
  • 可以作为参数传递给函数
  • 可以作为函数的返回值返回
  • 可以拥有动态创建并赋值的属性

函数是一等公民

什么是一等公民? 可以作为函数的参数,可以作为函数的返回值,可以赋值给变量

函数没有重载

当声明两个相同名字的函数时,后面一个会覆盖前面一个函数,实际上就是覆盖了引用第一个函数的变量

function funName(){console.log('杨旎奥')};
function funName(){console.log('杨紫')};
funName()

其他

  • 所有函数都有一个name属性,该属性保存的是该函数名称的字符串如
  • 每个函数都是Function类型的实例
  • 所有函数调用时都会有一个隐式参数 argument和this
  • ...
function myFun(){}
//name:'myFun'

函数调用的几种方式以及不同的调用方式有什么不同

定义函数有四种方式,那么函数的调用呢有几种方式呢?不同的调用方式有什么不同呢?上面有说到所有函数调用的时候都会有一个隐式参数 this那么不同的调用方式,this指向有什么不同呢?

作为函数进行调用 使用()操作符进行调用,应用了()操作符的表达式
//一般说作为函数进行调用我都默认为是全局调用函数 也就是函数前没有任何东西(可能这样的说法不对欢迎大佬补充指正)如
function fun(){
    console.log('杨紫666')
}
fun();
//此时的this 指向window

注:函数形成的上下文与在哪里调用无关,而与在哪里声明有关(后面会讲。。。感觉这个提示,额,好像没什么关系。。。)

作为方法进行调用(对象的方法)
var obj = {
    name:'杨紫'fun:function(){
        console.log(this.name)//杨紫
    }
    obj.fun();
    //this指向调用对象,也就是.之前的obj
};


构造函数
function Fun(){
    this.name= '杨紫';
    this.age=18;
}
var newP=new Fun();
dir(newP)//自己打印看看吧,看看this是哪个

new  xxx()  ==> typeof xxx 返回‘object’ [注意:new Function() ===> typeof 该类型却是‘function’] 那么new的时候会发生什么事呢?

1、创建一个新对象
2、将构造函数的作用域赋值给了新对象(this指向该新对象)
3、在函数里面添加this.xxx 就是给对象添加新属性
4、返回新对象(如果没有显式返回值,新创建的对象则作为构造器的返回值进行返回)
通过apply/call调用
//语法:
/*apply()方法*/
function.apply(thisObj[, argArray])

/*call()方法*/
function.call(thisObj[, arg1[, arg2[, [,...argN]]]]);


function fun(){
    console.log(this.name)
};
var obj = {
    name:'杨紫'
};
fun.call(obj);

//call/applay会导致fun里面的this指向obj里的this
自执行函数
(function(){})();
function(){}();
+function(){};
~function(){};
-function(){};
//自执行的函数的this都是指向window
var name = 'yz';
       var obj = {
           name: '杨紫',
           fn: (function() {
               console.log('111', this.name)
               return function() {
                   console.log('222', this.name)
               }
           })()
       };
       obj.fn()
  //哦。。你们猜猜 222里面的this 指向的哪个耶 嘻嘻
  • 严格模式 (在严格模式下 自执行函数的this 始终指向 window 即使 自执行函数作为某个对象属性的值 this 始终指向 window )
  • 非严格模式 (在非严格模式下 自执行函数的this 始终为undefined)

this方法的总结,不包含箭头函数中的this情况

那么函数调用的时候会发生什么事情呢?期待下一章吧!欢迎大佬补充指正谢谢!!!