javascript之function

本文介绍了JavaScript中创建函数的五种方式,包括具名函数、匿名函数、具名函数赋值、Function构造函数和箭头函数,并详细解析了每种方式的特点及使用场景。

创建函数的5中方式

1 具名函数

 function f(x,y){
     return x+y
 }
 f.name // f
复制代码

2 匿名函数

 var f
 f = function(x,y){
     return x+y
 }
 f.name // f
复制代码

3 具名函数赋值

var f
 f = function f2(x,y){ 
     return x+y
  }
  f.name // f2  what fuck 什么鬼?为啥是f2
  console.log(f2) // undefined
复制代码

4 Function构造函数 window.Function

 var f = new Function('x','y','return x+y')
 f.name // anonymous(匿名的意思)
复制代码

5 箭头函数

var f = (x,y) => {
     return x+y
 }
 //如果{}内只有一句话 则花括号和return可以同时省略
 var sum = (x,y) => x+y
 //如果()内只有一个参数,则可以省略括号
 var n2 = n => n*n
复制代码

函数的内存图

我们不妨模拟一下: 函数调用的过程其实就是eval(函数体)的过程

let f = {}
f.param = ['x','y']
f.fbody = 'console.log(111)'
f.call = function(){
    eval(f.fbody)
}
f.call() // 111
复制代码

f 是一个对象,把函数体封装成一个属性,通过f.call()去执行这个函数的函数体

scope 作用域

javascript在读取代码时会先将代码转换成 语法树

是否听过这么一句话?

如果在声明变量的时候不加var 你就是在声明全局变量 例如:a = 3

  1. 优先认为这是一个赋值语句
  2. 它会在当前作用域寻找 a的声明,如果没有,沿着作用域树向上查找,如果全局scope也没有变量a ,只能退而求其次,先声明变量a 再执行 a=3

就近原则

javascript 中作用域分为 全局作用域和函数作用域 只要有函数,就存在其对应的作用域 寻找一个变量的作用域 遵循 就近原则

this 和 arguments

  • this的值到底是什么?
  当前函数运行时所在的环境(即this的指向),也可以说 当前函数运行时所处的对象
复制代码
  • arguments是什么?
当前函数的参数集合,它是一个类数组(likeArray)
复制代码
var obj = {
  foo: function(){
    console.log(this)
  }
}

var bar = obj.foo
obj.foo() // 打印出的 this 是 obj
bar() // 打印出的 this 是 window
复制代码

最后两行函数的值为什么不一样?

函数的调用

   function f(x,y){return x+y}
   //第一种调用 语法糖
   f(1,2) //3
   //第二种调用 硬核玩家通过call调用函数 函数真正的使用方式应该是第二种
   f.call(undefined,1,2) //3   
复制代码

JavaScript 提供了call、apply、bind这三个方法,来切换/固定this的指向

call

用法

func.call(thisValue, arg1, arg2, ...)
复制代码

函数实例的call方法,可以指定函数内部this的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数

var obj = {};
var f = function () {
  return this;
};

f() === window // true  全局环境运行函数f时,this指向全局环境(浏览器为window对象)
f.call(obj) === obj // true call方法可以改变this的指向,指定this指向对象obj,然后在对象obj的作用域中运行函数f
复制代码

call方法的参数,应该是一个对象。如果参数为空、null和undefined,则默认传入全局(window)

var n = 123;
var obj = { n: 456 };
function a() {
  console.log(this.n);
}
a.call() // 123
a.call(null) // 123
a.call(undefined) // 123
a.call(window) // 123

a.call(obj) // 456
复制代码

call方法还可以接受多个参数,第一个参数为this,后面的所有参数组成这个方法的参数集合arguments,它是一个伪数组

var fn1 = function(x,y){
    return x+y
}
fn1.call(window,1,2) //this指向window arguments:[0:'1',1:'2',length:'2']
复制代码

apply

apply方法的作用与call方法类似,也是改变this指向,然后再调用该函数。唯一的区别就是:

  • 它接收一个数组作为函数执行时的参数

用法

func.apply(thisValue, [arg1, arg2, ...])
复制代码
function f(x, y){
  console.log(x + y);
}

f.call(null, 1, 1) // 2
f.apply(null, [1, 1]) // 2
复制代码

bind

  • bind方法用于将函数体内的this绑定到某个对象,然后返回一个新函数
  • bind方法的参数就是所要绑定this的对象
var counter = {
  count: 0,
  inc: function () {
    this.count++;
  }
};

var func1 = counter.inc;
func1();
counter.count // 0 this指向window 

var func2 = counter.inc.bind(counter);
func2();
counter.count // 1 通过bind绑定 this指向counter
复制代码

箭头函数

ES6中新出的函数创建方式

function log(a){
    return a*2
}
//只有一个参数时,可以不用()将参数括起来
let log = a => a*2

function add(a,b){
    return a+b
}
//方法体只有一句话时 可以不用{}将方法体括起来,也可以省略 return
let add = (a,b) => a+b

function sum(x,y){
    let s = x+y;
    return s
}
//方法体有多行时,需要用{}将方法体括起来
let sum = (x,y) => {
    let s = x+y;
    return s
}
复制代码

箭头函数的this

箭头函数内部的this是词法作用域,由上下文确定.也就是说箭头函数所处的作用域就是this的指向

setTimeout(function(){
    console.log(this)
}.bind({name:'dsying'}),1000)
//输出:{name:'dsying'}
复制代码
setTimeout(function(){
    console.log(this)
    setTimeout(function(a){
        console.log(this)
    },1000)
}.bind({name:'dsying'}),1000)
//输出:
//{name:'dsying'}
//window
复制代码

要想让第二个定时器也打印出{name:'dsying'}

setTimeout(function(){
    console.log(this)
    setTimeout(function(a){
        console.log(this)
    }.bind(this),1000)
}.bind({name:'dsying'}),1000)
//输出:
//{name:'dsying'}
//{name:'dsying'}
复制代码

由于this在箭头函数中已经按照词法作用域绑定了,所以,用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略:

setTimeout(function(){
    console.log(this)
    setTimeout(a => console.log(this),1000)
}.bind({name:'dsying'}),1000)
//输出:
//{name:'dsying'}
//{name:'dsying'}
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值