首页 > 技术文章 > JavaScript Function

lancgg 2019-02-19 21:39 原文

创建: 2019/02/19

更新: 2019/02/19 从【JavaScript 基础】迁入 函数相关内容

更新: 2019/02/26 从【【WIP】JavaScript 函数】迁入函数相关内容

更新: 2019/03/09 已完全覆盖迁入内容, 故删除迁入内容, 移到删除

完成: 2019/03/12

 

待完成事项: TODO

 

 函数的定义
 

 · 所有声明不分顺序,自动排序

 · 额外参数

  最后一个参数前加 ... ,最后一个参数获取后面所有参数,构成数组

function sample(a, ...b) {...} // 最后一个参数前加...

 · 参数的默认值

function sample(a=1) {...}

 注: 设为 undefined 时也会设定为默认值

      ES6以前为 a = a || 默认值 

 普通声明

 

 function test(a) {
    return a;
 }

 注: 被预处理

 函数字符来定义

 var sample = function(a) {
    return a;
 }
 呼出: sample(123);

 注: 不会被预处理

 Object来定义

 

var name = new function("x", "y", ... , "process")

 

 最后一个是处理,前面都是参数

 注: 不会被预处理

 箭头函数式来定义

 注: 不会被预处理

// 完整的定义方法
var a = (m, n) => { return m+n; };

// 一个参数时候可以省略括号
var b = x => { return x*x; };

// 没有参数时候不能省略括号
var c = () => { console.log("已呼出没卵用的函数"); };

// 函数只有return一行的时候可以省略return和括号{}
var d = (x, y) => x+y;

// 但若返回对象, 则省略后要加括号()
var e = () => ( {text: "没卵用啊"} )

 立即运行箭头函数 

(x => x/2)(100); // => 50

 与函数字符定义的区别 

 this的值

 箭头函数的this固定为外侧的this, 无法改变(apply/call/bind无效) 

(()=>{console.log(this);})(); //=> Window

 

 箭头函数

 this在函数定义时决定 

 箭头函数的this固定为外侧的this, 无法改变(apply/call/bind无效) 

 函数字符  this在函数呼出时决定

 

 arguments

 

 箭头函数  不含arguments
 函数字符  含arguments

 

 constructor  
 箭头函数

 不能作为constructor

 即不能用new生成实例

 函数字符  可以

 

 

 yield  
 箭头函数

 不能用

 函数字符  能

 

 

   

 

   
 嵌套函数  函数内部的函数
 位置  函数内部
 只可以在函数内部的"最外侧"(不能在if,for里面)
   同样声明上卷,作为函数内部的属性
   只能从定义的函数内部呼出
   
   
   
   
   
   
   
   
   
 函数的呼出
 函数的呼出方法  function sample() {}
 最普通的  sample();
 属性函数  object.func_name();
 呼出构造函数

 new Object();

 new的作用

    
var newObj = {};

 

 

 

newObj.__proto__ = Sample.prototype

 如果 Sample.prototype 不是object, 则直接带入 Object.prototype 

 

 

Sample.apply(newObj, a, b); // 就是new的对象和参数

 

   
 return newObj;

 但构造函数的return值是object的话, 返回return的那个

 

 call, apply  // TODO: 第9章
   
   
   
   
   
   

 即时函数

 (无名函数)

 定义与呼出同时进行
 
 普通  var f = function() {...};
 f();
 其他写法  (function() {...}) ();
   (function() {...} ());
 

 +function() {...} ();

+function show(a) {
  console.log(`a: ${a}`);
} (100); // => a: 100

 

 可以带名字,只有函数内部可以用该名称

 

  +function a(args) { a(); } (args);
 用途  构造不污染全局空间的命名空间
// TODO 8.7 补充即时函数用途
   
   
   
   
   
   
   
 函数的参数
  参数的省略  省略掉的为undefined
 undefined是没有赋值
 null是赋予的是空值
 不固定长度的参数  所有函数内部可用arguments
   Arguments Object
 自带属性  
 length  参数数量
 callee  现在执行的函数
   
   
   
 获取参数的方法  arguments[0]
 arguments[1]
 ...
 转换成数组  var params = [].slicce.call(arguments);
 定义无限长的参数的函数

 用arguments获取参数 

function sample(a) {
    var result = a;
    for(var i = 1; i < arguments.length; i++) {
        s += arguments[i];
    }
    return result;
}

  

   
   
   
   
   
 传值和传参  object参数传送的是参照(指针)
   
 递归函数
 三种写法  
 普通   
function sample(...) {
  if (...) {
    sample(...);
  }
}

 

 带一个本地可用名的无名函数  
var sample = function f(...) {
  if (...) {
    f(...);
  }
}

 

 不带本地名的无名函数

 获取当前函数  arguments.callee 

var sample = function(...) {
  if (...) {
    arguments.callee(...);
  }
}

 

   
   
   
   
 程序的编译与运行
 生成全局对象  
 解析程序

 最外侧的var全部作为全局对象的属性, 先代入undefined

 最外侧的函数也是全局对象的属性, 代入函数的参照

 注: 全局变量自带 dontDelete 属性, 无法用delete删除

 

 运行程序  用栈来运行
 单线程  JavaScript是单线程
 call对象及本地变量

 Call对象从程序内无法呼出, 包含如下属性

   函数的参数列表
   函数内的function函数声明
   函数内的var变量声明
   arguments
   呼出此函数的对象的参照

 

 this的值

 被呼出函数所属对象

 函数内部函数的this是全局变量

 最外侧的this  全局对象
 事件句柄内的this  触发该事件的元素
 构造函数内的this  生成的实例对象
 构造函数的prototype内的this  生成的实例对象
 最外侧直接呼出的函数内的this  全局对象

 嵌套函数的this

 (函数内部函数)

 全局对象

 注: 本应是外侧函数的Call对象,

      但是Call对象不能从程序内呼出.

      故参照全局对象

 用apply, call来呼出  手动指定this
   

 

 命名空间

 同名时优先更内侧的

 (此函数处没有就网上找, 找到全局范围也没有则抛出 ReferenceError )

 垃圾回收

 释放从全局对象无法到达的量

 不用在意 

   
 闭包
 

 JavaScript的所有函数都是闭包
 闭包内部可以有函数(闭包)

 # TODO: 完成这块

   
   
   
 命名空间
 用对象管理程序本地代码  全局对象会影响全局空间
var myApp = myApp || {};
myApp.login = ...;
myApp.configs = {}; //部分空间内部再划分部分空间
 
 用函数作为命名空间

 即时函数,对全局空间完全没影响

 用于小程序(所有程序内容都写在一个)

(function () {
    // 程序所有内容写在这里
})();

 

 

 module模式  
// 作为即时函数,把module相关传递给指定参数
var Module = Module || {};
(function (_module) {
    var name = "none"; // 私有变量
    function getName () { // 私有方法
      return name;
    }
    _module.showName() = function () { // 公共方法
      console.log(getName());
    }

})(Module);

 

   
   
函数也是对象

 函数也是对象

 (Function)

 ● 可以代入变量,对象属性, 数组元素

 ● 可以作为函数的参数, 返回值

 ● 可以有属性和方法

 ● 可以作为不带名字的字符, 即无名函数 function () {}

 ● 可以动态生成

 函数的属性(property)

 

 caller  呼出现在运行的函数的函数
 length  参数表长度
 name

 函数名

 注: 优先先赋予的名字 

var a = function (a, b, c) {};
var b = a;
console.log(a.name); // => a
console.log(b.name); // => a

 

var a = function test(a, b, c) {};
var b = a;
console.log(a.name); // => test
console.log(b.name); // => test

 

 prototype

 Function.prototype的属性

 apply()

 指定this和参数运行函数

 参数用数组指定 

function test(a, b) { ... }
test.apply(thisTarget, [a, b]);

 

 call()

 指定this和参数运行函数

 参数以连续排列方式指定

test.apply(thisTarget, a, b);

 

 bind()

 把函数的this绑定指定对象, 返回生成的新函数

 和apply/call区别: 不立即调用, 可以留着后面调用

 第二参数及之后参数若指定, 则固定用指定的值呼出函数(无法再改变)

function test() { return this.name }
var tom = { name: "none" };
var newTest = test.bind(tom);

 

 constructor()  Function constructor的参照
 toString()  把函数源代码以String形式返回
   

 

 

 添加自定义属性  
function test() {...}
test.newProperty = "sample"; // 和其他对象添加属性一样写法

 

   
   
 高阶函数
 定义  以函数为参数或返回值的函数
   
 回调函数
 定义   作为参数传递的函数
   

推荐阅读