青训营X豆包MarsCode 之this指针闭包 | 豆包MarsCode AI 刷题

43 阅读3分钟

作用域

以一个函数区块为边界的范围

变量提升

var只会将声明提升赋值不会提升

let不会提升

函数可以先调用后声明,默认存在(方便开发者)

结论:

  1. 函数默认提升
  2. varl变量可以提升,不能提升赋值
  3. 作用域是链式方式,从上向下=>限制在函数中
  4. 编译之前,函数那些会进行扫描,再进行编译(此时就可能会报错)

函数作用域有哪些(块级作用域概念)

var不受块级作用域影响

if(true){
 var d ='dd'
}
console.log(d)//dd

改用var的情况下,只有function可以隔离作用域->函数的模块隔离->js module->模块化

this上下文 (context)

我家门前有条河,上面有座桥,里面有群鸭

我家门前有条河,this上面有座桥,this里面有群鸭

利用儿歌方法,找谁调用的

this是在执行时动态读取上下文决定的,而非创建时

考察重点-各个使用态中的指针指向

  1. 函数中的直接调用-this指向的是执行全局

    function zhaowa(){
    console.log('函数内部的this',this)
    }
    zhaowa()
    //分析
    //this是zhaowa()调用,zhaowa()前文是window调用的
    
  2. 隐式绑定

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

改变绑定方式---显示绑定

  1. 改变this --bind ||call || apply

    o2.fn.call(o2)
    

面试题1

bind ||call || apply 区别

  1. call和apply传参不同

    call:依次传参

    apply:数组传参

    call和apply使用后直接执行了

    call(对象名(地址),参数,参数)
    
    apply(对项目(地址),[数组])
    
    bind同call传参,但是返回值是一个函数,不会立即执行,得自己调用
    
  2. 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 输出就是利用 闭包 模块内变量的返回

面试:垃圾回收、性能优化

形成私有变量