js面试题-画图看输出是啥

注:
log语句打印的是结果,直接显示信息;
dir语句打印的是内容,对显示对象的所有属性和方法。

1. 对象属性名 & 堆栈内存

a指向一个对象,对象存储在堆中
在这里插入图片描述

=> 数组和对象的区别

在这里插入图片描述
b是对象
把b作为obj的的属性名:obj[b]=100,即 [object,object]:100
(是把对象b…toString了)

a[b] 存的是[object,object]
a[c]也是,属性名相同,所以覆盖 a[b]= ‘培训’
=>Object.prototype.toString / valueOf
在这里插入图片描述

2. Symbol() 创建唯一值

结果:a[b] :珠峰
在这里插入图片描述
=>自己实现一个Symbol函数

3. 闭包

在这里插入图片描述
‘4’
alert结果都要toString()
立即执行函数
函数也是引用类型,存储在堆中,test函数中没有形参
函数每次执行,都会创建一个执行上下文(执行环境)

作用域链:test函数在定义时,自己是在哪个执行上下文中创建的,也就是上级作用域(test是立即执行函数的返回结果,所以是在这个立即执行函数里面定义的,这个结果是一个函数,所以这个函数也是在立即执行函数里定义的)执行的时候,会去上级作用域里找

分析:

  1. 预编译阶段,发生变量 | 函数声明提升,test是自执行函数的返回结果,是一个函数,指向该函数所在堆内存地址引用
  2. 执行阶段:自执行函数先执行,创建自己的执行上下文,返回一个函数,所以这个函数是在EC函数里定义的,形成作用域链
  3. 执行阶段:test(5),创建自己的执行上下文,当前上下文没有i定义,去上级作用域找到 ,i.toString(),输出
  4. 销毁阶段:test(5)执行完后,执行上下文内部没有被其他人占用的东西(看函数的地址啊,有没有函数在自己里定义的),就一定会销毁
    i=2所在的执行上下文不能被销毁,因为是右边函数的上级作用域,i 也就保存下来了,闭包
    在这里插入图片描述

var a = 0;
b=0
function A(a){
    A = function(b){console.log(a+b++)}
    console.log(a++)
}
A(1)//1
A(2)//4

A被重写了 GO代表全局变量
全局的a和b不变,闭包保护了全局不被污染

  1. 先是预编译阶段的函数,变量提升,A指向函数的堆内存地址
  2. 函数执行:
    调用A(1),进入A(1)函数的运行环境,创建A函数执行上下文,推入stack栈中:创建变量对象,作用域链,this
    (1)参数a=1, 自由变量A,是在父执行环境,也就是全局里面定义的,此时重写了全局里面的A的指向(新A是在A(1)EC里定义的)
    (2)alert(a++),A(1)里的a++【输出=>1】,a=2
    调用A(2)是,A是已经被重写过的,参数b = 2,(传入的),a去作用域链上找,此时A是在A(1)EC里定义的,所以a=2【输出=>4, 然后b++】
  3. 销毁阶段:此时A(最右边堆内存)是在A(1)EC里定义的,A所以(1)EC不销毁
    在这里插入图片描述

4. 面向对象

        function Foo() {
            getName = function () {
                console.log(1);
            };
            return this;
        }
        Foo.getName = function () {
            console.log(2)
        }
        Foo.prototype.getName = function () {
            console.log(3)
        }
        var getName = function () {
            console.log(4)
        }

        function getName() {
            console.log(5)
        }
        Foo.getName();//2
        getName()//4
        Foo().getName()//1
        getName()//1
        new Foo.getName()//2,先是成员调用Foo.getName(), new xx
        new Foo().getName()//3 先是new Foo(),创建实例,this变了
        new new Foo().getName()//3 先是new Foo(),然后new xxx.getName()

Foo()普通函数,在这里也是构造函数
Foo.getName 添加属性(执行过程中吧,按顺序加上属性,画原型链)
作为普通函数调用时,看有没有自由变量,看执行环境

在这里插入图片描述
在这里插入图片描述
有function , var,是ES5的语法,所以会有JavaScript 变量提升

  • JavaScript 中,函数及变量的声明都将被提升到函数(当前作用域)的最顶部。
  • var 提前声明,function提前声明
  • 所以变量可以在使用后声明,也就是变量可以先使用再声明。

function getName(){console.log(5)} 声明,但在当前作用域下已经有getName了,就不重新声明,直接赋值
函数也是对象,原型也是对象,在堆里
函数参数是私有的,变量在哪里定义,哪里就是上级作用域

实例调用方法,一定是原型上的方法
箭头函数不能被new =>箭头函数和普通函数的区别

js运算符优先顺序表 :new Foo.getName()无参数的new;new Foo().getName() 有参数的new
圆括号 > (成员,new(),函数调用) > new xx无参
在这里插入图片描述

5. js 异步

    async function async1(){
        console.log('async1 start')
        await async2();
        console.log('async1 end')
    }
    async function async2(){
        console.log('async2')
    }
    console.log('script start')
    setTimeout(function(){
        console.log('setTimeout')
    },0)
    async1()
    new Promise(function(resolve){
        console.log('promise1')
        resolve()
    }).then(function(){
        console.log('promise2')
    })
    console.log('script end')
    /*script start
	  async1 start
	  async2
	  promise1
	  script end
	  async1 end
	  promise2
	  setTimeout
    */

EC函数:立即执行函数
主栈 - EventQuene(微任务,宏任务)
代码走到异步时,会放到事件队列去,先把主栈代码执行完,才会去事件队列里找
(输出start的时候,已经是开始执行Js了)
await async2(); 执行async2,等待返回的结果(这是要现在执行async2,把等待放在微任务队列)
在这里插入图片描述

promise ,asyn,定时器都是异步的
浏览器是多进程的,渲染 & http请求。。
js是单线程=>浏览器只给js一个线程来渲染
事件队列 event queue
栈里的主线程代码执行完了,才会到事件队列里找(优先执行微任务【promise ,asyn,await】,然后宏任务【定时器,事件绑定,ajax】),放在主栈里执行


var a = ?
if(a == 1 && a == 2 && a == 3){
	console.log('条件成立');
}

6.转换数据类型

= = 转换数据类型
转换规则:
对象 = = 字符串:对象.toString()变为字符串之后,再比较
null = = undefined相等,但是和其他值比较,就不再相等了
NaN == NaN 不相等
剩下的都是转化为数字

例如 [10] = =10
[10].toString() -> “10” ->Number(“10”) -> 10

=== 绝对相等

方法1. 变成字符串,重写原型的toString()方法,利用==比较规则
或者valueof()
在这里插入图片描述

方法2. 劫持函数
获取obj.name :触发get()
设置obj.name属性:触发set()
defineProperty GETER拦截器中不能再次获取当前属性,所以使用++i,否则报错:栈溢出
在这里插入图片描述
在这里插入图片描述
a.shift 删除第一项并返回该项
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值