sourceinsight找不到函数声明_函数-笔记

747994f4199e250d953be8aa55ee3ee2.png

函数的声明

先声明,再调用,调用才是执行

如果同一个函数被多次声明,后面的声明就会覆盖前面的声明。

1、function

//语法
function 函数名(函数参数) {
  函数体
}

//示例
function sum(a, b) {
  return a + b
}

//之后使用sum()的形式,就可以调用相应的代码
let val = sum(3, 4)
console.log(val)

2、函数表达式

使用函数表达式,则不需要再加函数名,加上函数名表示该函数名只在函数体内部有效,在外部是无效的

// 语法
let 变量 = function(函数参数) {
  函数体;
}

//示例 
let val = function (a, b) {
  return a + b
};

// 使用val()的形式就可以调用相应的代码
val(3, 4)  

3、Function 构造函数

可以接受多个参数,但最后一个参数会被当成函数体,如果只有一个参数,那这个参数就是函数体

var add = new Function(
  'x',
  'y',
  'return x + y'
);

// 等同于
function add(x, y) {
  return x + y;
}

arguments对象

使用arguments对象可以获取该函数的所有传入参数,它只在函数体内部才可以使用

var f = function (one) {
  console.log(arguments[0]);
  console.log(arguments[1]);
  console.log(arguments[2]);
}

//arguments对象包含了函数运行时的所有对象,arguments[0]是第一个参数,arguments[2]是第二个参数,
// arguments[3]是第三个参数
f(1, 2, 3)
// 1
// 2
// 3

正常模式下,可以修改函数参数

var f = function(a, b) {
  arguments[0] = 3;
  arguments[1] = 2;
  return a + b;
}

f(1, 1)  // 5

严格模式下,arguments对象不会影响函数的实际参数

var f = function(a, b) {
  'use strict'; // 开启严格模式
  arguments[0] = 3;
  arguments[1] = 2;
  return a + b;
}

f(1, 1) // 2

arguments的length属性可以判断函数有几个参数

function f() {
  return arguments.length;
}

f(1, 2, 3) // 3
f(1) // 1
f() // 0

转为数组的两种方法

var args = Array.prototype.slice.call(arguments);

// 或者
var args = [];
for (var i = 0; i < arguments.length; i++) {
  args.push(arguments[i]);
}

用arguments的callee属性调用函数自身(严格模式下不可用)

var f = function () {
  console.log(arguments.callee === f);
}

f() // true

return 返回值

使用return的作用是终止函数的执行,并返会一个值,如果没有return将返回undefined

 function sum(a, b) {
   return a + b
}
console.log(sum(3, 4)) // 7


 function sum(a, b) {
}
console.log(sum(3, 4)) // undefined

return和console.log的区别

return是返回一个值,这个值是能够赋值在另外一个变量的,而console.log仅仅是展示在控制台,并不会赋值

function sum(a, b) {
   return a + b
}

let a = sum(3, 4)
a  //   7


function sum(a, b) {
  console.log(a + b)
}


let a = sum(3, 4)
a  // undefined

箭头函数

箭头函数简化函数表达式

//语法
const fn = name => 'hello' + neme

//等价于
const fn function(neme) {
   return 'hello' + neme
}

只有一个参数, ( ) 可以省略,多个参数要加括号

const sum = (a + b) => a + b

函数体如果只有一个表达式, { } 可以省略,如果有多个表达式必须要加上,并且用return返回

const a = x => {
    if (x > 0) {
        return x * x;
    }
    else {
        return - x * x;
    }
}
sonsole.log(a(5)) // 25

// 等同于
const a = function(x) {
  if(x > 0) {
    return x * x 
  } else {
    return - x * x
  }
}
sonsole.log(a(5)) // 25

如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错

var func = () => ({foo: 1});

箭头函数嵌套简写

const add = a => b => a + b

add(3)(4)  // 7

//等同于
const add = function(a) {
 return  function(b) {
          return a + b
 }
}

add(3)(4)  // 7

函数的命名规范

  • 前缀应为动词、或动词加宾语
  • 小驼峰方式 ( 构造函数使用大驼峰命名法 )

2bb49fd0a6611b4091cb80a97729b70a.png

示例:

求值(sum)、隐藏(hide)、展现(show)打印名字(printName)

说你好(sayHello)、得到数据(getDate)、设置数据(setDate)

声明前置(变量提升)

var声明的变量会提升到代码的头部

// 表明上是先调用,再声明
console.log(a)
var a = 3

//实际上等同于
var a
console.log(a)
a = 3 
// 输出结果为undefined

在函数作用域var声明的变量也存在变量提升

function fn() {
  console.log(a)
  var a = 3
  console.log(a)
}

//等价于
function fn() {
   var a
   console.log(a)
   a = 3
   comsole.log(a)
}

// 输出结果为 undefined  3

注意:用let声明不会存在变量提升,上面的写法用let声明就会报错

在JavaScript中,函数名视同变量名,所以也存在变量提升

// 表明上是先调用,再声明
fn()

function fn() {
  console.log(hello)
}
// 实际不会报错,等同于
functiom fn() {
  console.log(hello)
}

fn()

如果是函数表达式会报错

fn()

var fn = function () {
  console.log(hello)
}

// 会报错,等同于
var fn 
fn()
fn = function() {
  console.log(hello)
}

// 调用fn的时候,fn只是被声明了,还没有赋值,等于undefined,所以会报错

如果用function 和var 声明的函数表达式是同一个函数,会采用var声明的函数表达式

var f = function () {
  console.log('1');
}

function f() {
  console.log('2');
}

f() // 1  因为变量提升,后面的函数不会覆盖前面的

函数作用域

全局变量和局部变量

对于顶层函数来说,在函数外部声明的变量就是全局变量,它可以在函数内部读取,在函数内部声明的变量,就是局部变量,外部无法读取,并且会在局部变量所在的作用域中覆盖同名的全局变量

// 全局变量
var a = 1 
function fn() {
   console.log(a)
}
// 输出结果1


//局部变量
function fn() {
   var a = 1
}
a  // 报错,外部无法读取

//局部变量与全局变量同名
var a = 1 
function fn() {
  var a = 2 
  console.log(a)
}

fn() //  2  覆盖同名的全局变量
a    //  1

作用域链

函数在执行的过程中,先从自己内部找变量,如果找不到,再从创建当前函数所在的作用域去找,以此往上,直到全局变量(找的是变量此刻的状态)

862ae8574419ec73c8e4d5846eb6ff22.png

aab5a5bcae75d7adaaa870223ee93ae7.png

52ccb9bae15807b66fce29f2f49c7170.png
ket a = 0 
function foo() {
   bar()      // 执行的时候,a还未被赋值,只是声明前置了
   var a = 1
   function bar() {
      console.log(a)  // 输出结果为undefine,内部和创建bar函数所在的作用域找,而且是a此时的状态
  }
}

// 等价于
let a = 0
function foo() {
   var a   //  此时的a为undefined
   bar() 
   a = 1
   function bar() {
      console.log(a)  
  }
}

立即执行函数表达式

作用是隔绝彼此的作用域

// 语法

( function () { 
    函数体 
})()

// 示例
function () {
    let a = 3
    let b = 4
    console.log(a + b)
};
function () {
    let a = 2
    let b = 1
    console.log(a - b)
}
//  上面这段代码会报错

(function () {
    let a = 3
    let b = 4
    console.log(a + b)
})();

(function () {
    let a = 2
    let b = 1
    console.log(a - b)
})()
//改用立即执行函数表达式不会报错

递归

函数调用自身,就是递归,必须设置终止条件,否则会出现死循环

//用递归实现n的阶乘
// 5!5*4!4*3!3*2!2*1!1!
function fact(n) {
   if(n === 1) return 1
   return n*fact(n-1) 
}
console.log(fact(6))  // 720

// 实现斐波那契数列  fib(n) = fib(n-1) + fib(n-2)
// 1 1 2 3 5 8 13 21 34

function fib(n) {
if(n === 1 || n===2) return 1
return fib(n-1) + fib(n-2)
}
console.log(fib(5)) // 5

递归优化:https://zhuanlan.zhihu.com/p/141440886

柯里化

把接受多个参数的函数变成接受一个单一参数的函数,然后里面返回新的函数

function add(a) {
  return function(b) {
    return a + b
  }
}

add(3, 4)
// add(3)(4)

回调

回头再调用

function callMe(name,callBack) {
  callBack(name)
}
callMe('hello',function(name) {
    console.log('hi' + name)
})

参考来源:

饥人谷课件

ES6阮一峰教程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值