面试考点比较密集
参考阮一峰JavaScript函数
函数的五种声明方式
具名函数
var
声明一个变量,七种数据类型
function
声明一个函数,是个特例
不写return
自动加上return undefined
function f(x,y){
return x+y
}
f.name // 'f'
关于console.log()
-
console.log()
返回undefined
-
console.log()
会在传入的参数里首先调用toString()
方法
- 但是当打印到控制台的时候,没有写双引号,是chrome浏览器的原因
修改:比如可以在重写console.log()
匿名函数
var f
f = function(x,y){
return x+y
}
f.name // 'f'
如果要声明匿名函数,就一定要把它赋给一个变量
var 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.(可以访问的区域就是绿色圈起来的区域)
window.Function
window.Function
var f = new Function('x','y','return x+y')
f.name // "anonymous"
不常用
箭头函数
箭头函数都是匿名函数,没有名字,就像是匿名函数的简写形式
五种方式总结
函数的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"
函数的本质
函数就是一段可以反复调用的代码块。函数是可以执行一段代码的对象。
调用的英文单词call
函数在内存中为字符串
函数在内存中:
即函数也是一个对象,广义上
eval()函数
模拟函数本质
函数是一个对象,里面有参数,函数体,调用方法
f是函数,是对象,f.call()是一个执行函数体的方法
总结
js中有七种数据类型,
number string boolean null undefined symbol object
前六种是简单类型,object是前6种的各种组合,所以是复杂类型
原型链
函数的调用:f(1,2)与f.call(undefined,1,2)
f(1,2)
是简单用法
f.call(undefined,1,2)
才是真实的用法
用call 便于理解this,是硬核技术
call用法:
参数从第二个开始
this和arguments
this就是f.call()里面的第一个参数,在JAVA里面比较有用,在JS里没什么用。当初是为了像JAVA而设计的,在JS里面没什么用,this就是一个参数。
arguments是参数数组
this
了解这篇博文this 的值到底是什么?一次说清楚
特例:当call()的第一个参数是undefined的时候, this 是 window.
当启用严格模式的时候,call 里的第一个参数是什么,this 就是什么
this的作用先不说
arguments 是参数组成的伪数组
arguments是一个伪数组:里面有0123这些次序,也有length,长得像数组,但是.伪数组的__proto__
没有指向的是 Array.prototype,或者说原型链中没有Array.prototype,即原型链中没有和Array.prototype有关的 ,也就是说只是一个像数组的对象而已.
没有 push
换句话说:
arguments是一个伪数组,伪数组的意思就是长得像数组,但是它的__proto__
指向的不是Array.prototype,并且伪数组的整个原型链中都没有Array.prototype,即也使用不了a.push()之类数组特有的函数API(没有数组的公有属性)。arguments就是一个长得像数组的普通对象。
call stack 调用栈
每进入一个函数,就在栈里记录一个记号,当调用完之后return的时候,就跳到做的记号哪里,弹出栈里的记号
Stack Overflow错误
堆栈溢出
超出call stack调用栈
segment fault也是一种错误,c语言里面的
作用域
作用域了解一下这篇JS里的作用域,变量提升与函数提升
什么情况下直接使用 a=1
会使a直接变成全局变量(window.a
)?
当写a=1
这个代码的时候,首先计算机会认为这是赋值,当发现当前作用域没有声明a
的时候,就继续往上找,看看上一层的作用域有没有声明a
,就这样,一直找到window
层即全局作用域层,就直接给全局变量window
自动声明一个a.
就近原则,哪一个scope离赋值最近,赋值的就是哪一个作用域
这个f4里面的a只能是他自己本身的作用域和他的父作用域,跟f1里面的a=2没有关系
f4打印出来的a是1
有函数就有作用域。
一定要变量提升,一开始看见题目就要变量提升。
浏览器在画作用域树的时候都是先找到所有变量声明,然后把这些声明都放到最前面。
闭包
闭包就是如果一个函数使用了它范围外(作用域)的变量,那么 【这个函数+这个变量】组合的整体 就叫做闭包。
了解这篇 JS 中的闭包是什么?
题目
- 1.f1.name 是多少???
var f1 = function f2(){};
答:f2
- 2.f2.name 是多少???
var f1 = function f2(){};
答:什么都不是
- 3.打印出什么???
var f1 = function f2(){};
console.log(f2);
答:f2 is not defined(f2 不存在,而且 f2 不是 undefined)
- 4.非严格模式下,打印出什么???
function f(){
console.log(this)
}
f.call(1)
答:Number 对象 1
这里是说返回的是一个对象,类型为Number, 字面量的表示是1 不是字符串 number 1 因为数字、字符串 是特殊的对象, 是对象的字面量表示方法,所以数字才有属性。 console.log(this)的时候就把它强制还原为原始对象状态,就像 new Number(1)
- 5.严格模式下,打印出什么???
function f(){
'use strict'
console.log(this)
}
f.call(1)
答:1
- 6.下面的例子不带参数,打印出什么???
function f(){
console.log(this)
}
f.call()
答:window
- 7.严格模式下,不带参数,打印出什么???
function f(){
'use strict'
console.log(this)
}
f.call()
答:Undefined
- 8.a的值是什么???
var a = console.log(1)
答:Undefined
- 9.a 的值是什么???f
function f(){
return 1
}
a = f
答: 函数 f
- 10.a 的值是什么???f.call()
function f(){
return 1
}
var a = f.call()
答: 1
- 11.a的值是什么???
var a = 1,2
答:报错
因为 = 和 , 都是运算符 但= 的优先级更高 逗号是最低的
- 12.a 的值是什么???
var a = (1,2)
答:2
- 13.a 的值是什么???
var a = (1, console.log(2))
答:Undefined,和上面 var a = console.log(1)
一样
- 14.a 的值是什么???
function f(){
return function f2(){}
}
var a = f.call()
答:函数f2
- 15.b 的值是什么???
function f(){
return function f2(){}
}
var a = f.call()
var b = a.call()
答:undefined 结合上面的看一下,a的值是f2,然后b的值 = f2.call() ???
- 16.a 的值是什么???
function f(){
return function f2(){}
}
var a = f.call().call()
答:和上一题一样的。
- 17.打印出什么???
function f1(){
console.log(this)
function f2(){
}
}
var obj = {name: 'obj'}
f1.call( obj )
答:对象obj,因为,这个就像上面的f1.call(1)
结果就是 Number 对象 1 效果一样。
- 18.打印出什么???
function f1(){
function f2(){
console.log(this)
}
f2.call()
}
var obj = {name: 'obj'}
f1.call( obj )
答: window 对象 这里面的f2.call()是不带参数的,所以这里面的this就是window对象。不理解的话就看看上面第6题,f.call()不带参数的情况下,打印出的结果。
- 19.为什么两个 this 值不一样?
function f1(){
console.log(this) // 第一个 this
function f2(){
console.log(this) // 第二个 this
}
f2.call()
}
var obj = {name: 'obj'}
f1.call( obj )
答:
- 每个函数都有自己的 this,为什么会一样?
- this 就是 call 的第一个参数,第一个 this 对应的 call 是 f1.call(obj),第二个 this 对应的 call 是 f2.call()
- this 和 arguments 都是参数,参数都要在函数执行(call)的时候才能确定
- 你以为名字一样值就一样吗?