作用域
以一个函数区块为边界的范围
变量提升
var只会将声明提升,赋值不会提升
let不会提升
函数可以先调用后声明,默认存在(方便开发者)
结论:
- 函数默认提升
- varl变量可以提升,不能提升赋值
- 作用域是链式方式,从上向下=>限制在函数中
- 编译之前,函数那些会进行扫描,再进行编译(此时就可能会报错)
函数作用域有哪些(块级作用域概念)
var不受块级作用域影响
if(true){
var d ='dd'
}
console.log(d)//dd
改用var的情况下,只有function可以隔离作用域->函数的模块隔离->js module->模块化
this上下文 (context)
我家门前有条河,上面有座桥,里面有群鸭
我家门前有条河,this上面有座桥,this里面有群鸭
利用儿歌方法,找谁调用的
this是在执行时动态读取上下文决定的,而非创建时
考察重点-各个使用态中的指针指向
-
函数中的直接调用-this指向的是执行全局
function zhaowa(){ console.log('函数内部的this',this) } zhaowa() //分析 //this是zhaowa()调用,zhaowa()前文是window调用的 -
隐式绑定
function fn(){
console.log('隐式绑定的this',this.a)
}
const obj={
a:1,
fn
}
obj.fn=fn
obj.fn()//1
//分析
//obj执行了fn()
//所以河是obj,那么河中的a就是1
面试题1:
const foo={
bar:100,
fn:function(){
console.log(this.bar)
console.log(this)
}
}
let fn1=foo.fn
fn1()
//undefined
//undefined
//分析
//this执行时候需要fn,但是fn又给了fn1,fn1是window执行的,所以为undefined
面试题2
const o1={
text:'o1',
fn:function(){
console.log('o1fn_this',this)
return this.text
}
}
const o2={
text:'o2',
fn:function(){
return o1.fn()
}
}
const o1={
text:'o3',
fn:function(){
let fn=o1.fn
return fn()
}
}
console.log('o1fn',o1.fn)
console.log('o2fn',o2.fn)
console.log('o3fn',o3.fn)
//分析
//fn是o1执行,o1中的text就是o1
//o2执行的是function函数,fn()还是o1执行
//fn是全局window调用的,但是全局没有text,所以是undefined
改变绑定方式---显示绑定
-
改变this --bind ||call || apply
o2.fn.call(o2)
面试题1
bind ||call || apply 区别
-
call和apply传参不同
call:依次传参
apply:数组传参
call和apply使用后直接执行了
call(对象名(地址),参数,参数)apply(对项目(地址),[数组])bind同call传参,但是返回值是一个函数,不会立即执行,得自己调用 -
bind 直接返回方式不同
bind只改变,返回一个函数
面试题2
bind原理|| 手写bind
手写解题---说明原理,写下注释
根据注释补全代码
//bind位置--挂在在Function.prototype
//bind是什么?
//输入:args特点,第一项是新的this,第二项到最后一项是函数传参
//返回:返回的是一个函数=>构造一个函数=>
//这个函数返回原函数的结果且继承传参
Function.prototype.newBind=function(){
const _this=this args=Array.prototype.slice.call(arguments)
const newThis=args.shift()
return function(){
return _this.newApply(newThis,args)
}
}
Function.prototype.newApply=function(context){//边缘检测 亮点
if(typeof this!=='function'){
throw newTypeError('使用正确函数进行调用')
}
//防止报错
context =context ||window
//执行函数替换---
context.fn=this
//此时this挂在在了context.fn上面
let result=arguments[1]
?context.fn(...arguments[1])
:context.fn()
delete context.fn
//返回结果
return result
}
闭包
作用域和上下文=>束缚=>突破束缚
闭包
function mail(){
let content='mail'
return function(){
console.log(content)
}
}
const envelop=mail()
//局部变量content逃逸到外部
=>js module 输出就是利用 闭包 模块内变量的返回
面试:垃圾回收、性能优化
形成私有变量