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 刪除第一項並返回該項
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章