工作生活

function详解

2019-07-05  本文已影响0人  没了提心吊胆的稗子

1、函数的基础操作

函数指实现某一个功能的方法,也叫子程序,OOP中的方法
JS中函数有两部分:创建函数执行函数
创建的时候函数被保存成字符串没有实际意义;执行的时候才实现它真正的意义。
多次用到的功能就可以封装成一个函数,提高开发效率;页面代码的冗余度减少了,代码重复利用率也提高了:低耦合高内聚

2、函数核心操作原理

创建函数:

  • 声明函数(跟变量声明一样的操作)
  • 浏览器开辟一个内存空间(分配一个16进制的地址),保存函数体中的代码

执行函数:

  • 函数执行的时候,浏览器首先会开辟一个新的私有作用域来执行之前编写的代码
  • 形参赋值
  • 私有作用域中的变量提升
  • 把之前存储的字符串格式的代码自上而下执行
  • 私有作用域销毁(私有作用域中有被外界引用的部分时不销毁)

闭包
函数执行会形成一个私有作用域,把私有变量保护起来不受外界干扰

栈内存和堆内存
栈内存又叫作用域,提供一个JS代码执行的环境
堆内存保存引用数据类型需要存储的内容(相当于一个仓库)

3、形参和实参

形参:执行函数的时候需要执行者传递进来的值
实参:执行者执行的时候传递给形参的具体值

function sum(num1, num2){  //num1, num2相当于在当前作用域下已经声明(var)
  var total = num1 + num2;
  console.log(total);
}
sum(10); // 只传递了num1,num2没传递就默认为undefined
// 在可能出现不传值的情况下可以设置默认值
function sum(num1, num2){  //num1, num2相当于在当前作用域下已经声明(var)
  // 容错处理
  // num1 === undefined ? num1= 0 : null;
  // typeof(num2)  === 'undefined' : num2=0 : null; // 项目中常用
  // 逻辑或的方式
  num1 = num1 || 0;
  num2 = num2 || 0;
  var total = num1 + num2;
  console.log(total);
}
sum(10); // 只传递了num1,num2默认0

4、arguments实参集合

不知道具体传递参数的数量时,无法设置形参的个数,就需要使用函数内置的实参集合arguments
1、arguments只有函数才有
2、不管执行函数时是否传递实参,arguments都是存在的,不传递实参的时候arguments为空集合,传递的时候arguments包含所有传递的实参
arguments是一个类数组集合,有length属性,根据下标获取实参信息

arguments.calee 存储的是当前函数本身
arguments.calee.caller 存储的是当前函数的宿主函数,没啥用基本
严格模式下不许使用以上两个属性

5、JS中的返回值return

闭包机制使得私有作用域会保护里面的私有作用域
return 返回的都是值,若函数中没有return或者return;,结果都是undefined,return后面的代码不执行。

function sum() {
    var total = null;
    for (let i = 0; i < arguments.length; i++) {
        var cur = arguments[i];
        !isNaN(cur) ? total += cur : null;
    }
    return total;
    //此处不是把total这个变量返回,而是返回total中存储的值 <=> 60
}
console.log(sum(10, 20, 30)); // 60

6、匿名函数

没有名字的函数

  • 函数表达式, 把一个没有名字的函数赋值给一个变量或者某个元素的点击事件
oBox,onclick = function(){
  // do something
}
  • 自执行函数,前面的符号;,-,+,~,!都可以
;(function (n){
  //  do something
  // n是形参
})(10);
// 以下都是自执行函数,符号只是控制语法的规范 
~(function (n){})(10);
-(function (n){})(10);
+(function (n){})(10);
!(function (n){})(10);

函数本身也有一些属性
length:形参的个数
name:函数名
prototype:类的原型,在原型上定义的方法都是当前类实例的公有方法
__proto\__:把函数当做一个普通对象,指向Function这个类的原型

函数在JS中是最复杂也是最重要的
一个函数存在多面性:
1、它本身是一个普通的函数,执行的时候行程私有的作用域(闭包),经历形参赋值,变量提升,代码执行,执行完成后栈内存销毁或者不销毁(当函数内的某一部分被外界变量接收时不销毁)。
2、它也可以是一个类,拥有自己的实例,有一个prototype属性是自己的原型,它的实例都指向这个原型。
3、普通对象,是Function这个类的一个实例,实例都是对象数据类型,作为对象可以有自己的一些私有属性,也可以通过__proto\__属性找到Function.prototype
三者之间没有必然联系

function Fn(){
  var num = 500;
  this.x = 100;
}
Fn.prototype.getX = function(){
  console.log(this.x);
}
Fn.aaa = 10000;
var f = new Fn;  // 此时Fn中的this是实例f
console.log(f.num);  // undefined
console.log(f.aaa);  // undefined
var res = Fn();
console.log(res);  // undefined 此时Fn中的this是window

Function类的原型Function.prototype是函数数据类型的值,但是相关操作和其他函数的原型一样

上一篇 下一篇

猜你喜欢

热点阅读