JavaScript函数
面试考点比较密集
参考阮一峰JavaScript函数
我的博客:关于作用域,变量提升,函数提升的个人理解笔记
1.函数的五种声明方式
1.1 具名函数
var
声明一个变量,七种数据类型function
声明一个函数,是个特例
不写return
自动加上return undefined
function f(x,y){
return x+y
}
f.name // 'f'
1.1.1 关于console.log()
-
console.log()
返回undefined
-
console.log()
会在传入的参数里首先调用toString()
方法
- 但是当打印到控制台的时候,没有写双引号,是chrome浏览器的原因
- 比如可以在重写
console.log()
1.2 匿名函数
var f
f = function(x,y){
return x+y
}
f.name // 'f'
如果要声明匿名函数,就一定要把它赋给一个变量
1.3var x = function y(){}
var f
f = function f2(x,y){ return x+y }
f.name // 'f2'
console.log(f2) // undefined
直接声明function y(){}
与var x = function y(){}
的区别
然后刷新页面
直接报错,说y没有定义
区别:
第一种方式可以打印,第二种打印说不存在.
第一种整个外面的区域都可以访问y,第二种只有函数内部才可以访问到y.(可以访问的区域就是绿色圈起来的区域)
1.4 window.Function
window.Function
var f = new Function('x','y','return x+y')
f.name // "anonymous"
基本不会用
1.5 箭头函数
箭头函数都是匿名函数,没有名字,就像是匿名函数的简写形式
三种
箭头函数
var f = (x,y) => {
return x+y
}
var sum = (x,y) => x+y//如果return只有一个,可以省略return和{}
var n2 = n => n*n//如果参数只有一个,可以省略()
五种方式总结
2.函数的name属性
所有的函数都有一个name属性,他是一个字符串
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'
console.log(f2) // undefined
4window.Function
var f = new Function('x','y','return x+y')
f.name // "anonymous"
5箭头函数
var f = (x,y) => {
return x+y
}
f.name//"f"
3.函数的本质
3.1函数的调用
调用的英文单词call
函数在内存中为字符串
3.1.1函数在内存中:
3.1.2 eval()函数
给一个字符串.返回的为:字符串转化成代码然后执行.'
3.1.3函数就是对象
模拟函数本质
函数是一个对象,里面有参数,函数体,调用方法
f是函数,是对象,f.call()是一个执行函数体的方法
总结
js中有七种数据类型,
number string boolean null undefined
symbol **object**
前六种是简单类型,object是前6种的各种组合,所以是复杂类型
原型链
3.1.4函数的调用:f(1,2)
与f.call(undefined,1,2)
f(1,2)
是简单用法f.call(undefined,1,2)
才是真实的用法
用call 便于理解this,是硬核技术
call用法:
参数从第二个开始
4.this
和arguments
arguments是参数数组
4.1 this
特例:当call()
的第一个参数是undefined
的时候, this
是 window
.
当启用严格模式的时候,call
里的第一个参数是什么,this
就是什么
this的作用先不说
4.2 arguments
是参数组成的伪数组
伪数组:里面有0123这些次序,也有length,长得像数组,但是.伪数组的__proto__
没有指向的是 Array.prototype
,或者说原型链中没有Array.prototype
,即原型链中没有和Array.prototype
有关的 ,也就是说只是一个像数组的对象而已.
没有 push
5 call stack 调用栈
每进入一个函数,就在栈里记录一个记号,当调用完之后return的时候,就跳到做的记号哪里,弹出栈里的记号
调用演示:
普通调用
嵌套调用
递归调用
5.1 Stack Overflow
错误
segment fault也是一种错误,c语言里面的
6. 作用域
什么情况下直接使用 a=1
会使a直接变成全局变量(window.a
)?
当写a=1
这个代码的时候,首先计算机会认为这是赋值,当发现当前作用域没有声明a
的时候,就继续往上找,看看上一层的作用域有没有声明a
,就这样,一直找到window
层即全局作用域层,就直接给全局变量window
自动声明一个a.
就近原则,哪一个scope离赋值最近,赋值的就是哪一个作用域
我的博客:关于作用域,变量提升,函数提升的个人理解笔记
这个f4里面的a只能是他自己本身的作用与和他的父作用域,跟f1里面的a没有关系
f4打印出来的a是1
所有的代码解析完毕,这时候i已经是6.
所以当点击的时候,已经是解析完毕后的i,点击的时候就是执行最开始绑定过的函数,点击相当于在最后写下执行函数的代码,这时候i已经是6了,所以打印出来的是6.for循环结束之后就是6.
liTags[i].onclick = function(){
console.log(i)
}//在这里只是声明函数,并没有调用,运行这段代码只会解析代码,不会运行函数
//当点击事件发生的时候,就相当于调用这个函数,当调用的时候,已经被解析成6了点击速度不可能超过解析速度
同理,下面代码打印出的是6
闭包定义
题目
特例:当call()
的第一个参数是undefined
的时候, this
是 window
.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。