js函数

function(输入1,输入2){
//return undefined  你不写也会返回undefined 所以经常在开发者模式下写一个函数下面会有undefined返回值
}

console.log(x)
打印什么和返回什么一点都不一样


image.png

JS的问题之一


image.png

image.png

为什么上面定义function y(){} console.log(y) 就可以,下面var x = function y(){} console.log(y) 就会报错,显示y未定义 这个说明js不一致性,下面的y只在绿色区域内有效


函数的5种声明方式

1.function f(x,y){return x+y}

2.f = function(x,y){return x+y}

3.f = function x(){}

4.f = new Function ('x','y','return x+y')

5.f = (x,y) => x+y

函数的name属性(毫无逻辑)

function f(){}
undefined
f.name
"f"//正常

var f1 = function(){} 
undefined
f1.name
"f1"//正常

var f2 = function f3(){} 
undefined
f2.name
"f3"//f3?what 之前不是说f3能用的地方很少。。

var f4 = new Function('x','y','return x+y')
undefined
f4.name
"anonymous"(匿名)// what?名字叫匿名。。。

var f5 = (x,y) => x+y
undefined
f5.name
"f5"// 正常

函数的本质 调用:call

函数是什么?

函数是一段可以反复调用的代码块。函数还能接受输入的参数,不同的参数会返回不同的值。

创建函数内存图


image.png
用纯对象来实现函数
var f = {} 定义一个对象
f.name ='f' 对象name属性是'f'
f.params=['x','y'] 对象的元素是'x','y'
f.functionBody = 'console.log("fff")' 对象的函数体是 'console.log("fff")'
f.call = function(){
  return window.eval(f.functionBody) 
} 对象的call属性通过eval执行函数体
f.call() 执行f.call  f和f.call()的区别 一个是对象,一个是执行函数

什么是eval() 就是你给eval一堆字符串,他把字符串当成代码来执行


世纪难题:f(1,2) <=> f.call(undefined,1,2) 两者是等价的,但是第二个才是真正的调用

第一个是糖 第二个是硬核!!

现在f 是函数 f.call()是函数调用


this和arguments

image.png

1.call 的第一个参数可以用this得到
2.call的后面的参数可以用arguments得到

在普通模式下
f=function(){console.log(this)}
ƒ (){console.log(this)}
f.call(undefined)
Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
call第一个参数传入undefined会打印出window(小写,浏览器抽风会显示成大写) 
image.png
在严格模式下
f1 = function(){
'use strict'
console.log(this)
}

f1.call(undefined)
VM204:3 undefined

call 传入的第一个参数是什么,this就是什么,这里this就是undeifned
image.png

综上所述,this就是call传入的第一个参数

arguments 是伪数组,怎么按断是不是一个伪数组
就是看他的- - proto - -有没有指向Array.prototype
或者说看他的原型链中有没有 Array.prototype


函数的Call Stack 调用栈

image.png

普通调用

普通调用.gif

递归调用

递归调用.gif

嵌套调用

嵌套调用.gif

作用域
函数当前的执行环境,作用域也可以被在层次结构中分层,以便子作用域可以访问父作用域,但反之不行。

image.png

传统错误:

function f(){
  a=3
}
这里的a=3就是在声明全局变量,其实并不然

首先这只是一个赋值表达式,当前作用域没有a这个变量,会沿着树也就是作用域链寻找,一直寻找到最外层window作用域中,仍然寻找不到,此时就会退而求其次,在window作用域中先声明变量a,然后再赋值a=3,所以a就成了全局变量

经典面试题:

面试题1
var a = 1
function f1(){
alert(a) // 是多少 undefined
var a = 2
}
f1.call()
拿到代码直接做——必然会错。请先提升声明

面试题2
var a = 1
function f1(){
var a = 2
f2.call()
}
function f2(){
console.log(a) // 是多少1
}
f1.call()
拿到代码直接做——必然会错。请先提升声明

面试题3
var liTags = document.querySelectorAll('li')
for(var i = 0; i liTags[i].onclick = function(){
console.log(i) // 点击第3个 li 时,打印 2 还是打印 6?6
}
}
拿到代码直接做——必然会错。请先提升声明


闭包

如果一个函数,使用了他范围外的变量,那么(这个函数+这个变量)就叫做闭包

你可能感兴趣的:(js函数)