前端面試送命題 JS三座大山

2022-04-01 20:19:03 字數 4778 閱讀 9333

說到原型,就不得不提一下建構函式,首先我們看下面乙個簡單的例子:

function

dog(name,age)

let dog1 = new dog("哈士奇",3);

let dog2 = new dog("泰迪",2);

首先創造空的物件,再讓 this 指向這個物件,通過 this.name 進行賦值,最終返回 this,這其實也是 new 乙個物件的過程。

其實: let obj = {} 是 let obj = new object() 的語法糖; let arr = 是 let arr = new array() 的語法糖; function dog() 是 let dog = new fucntion() 的語法糖。

那什麼是原型那?在 js 中,所有物件都是 object 的例項,並繼承 object.prototype 的屬性和方法,但是有一些是隱性的。

我們來看一下原型的規則:

1.所有的引用型別(包括陣列,物件,函式)都具有物件特性;可自由擴充套件屬性。

var obj ={};

obj.attribute = "三座大山";

var arr =;

arr.attribute = "三座大山";

function

fn1 () {}

fn1.attribute = "三座大山";

2.所有的引用型別(包括陣列,物件,函式)都有隱性原型屬性(proto), 值也是乙個普通的物件。

console.log(obj.__proto__);

3.所有的函式,都有乙個 prototype 屬性,值也是乙個普通的物件。

console.log(obj.prototype);

4.所有的引用型別的proto屬性值都指向建構函式的 prototype 屬性值。

console.log(obj.__proto__ === object.prototype); // true

5.當試圖獲取物件屬性時,如果物件本身沒有這個屬性,那就會去他的proto(prototype)中去尋找。

function

dog(name)

dog.prototype.callname = function

()let dog1 = new dog("three mountain");

dog1.printname = function

()dog1.callname();

//three mountain wang wang

dog1.printname(); //

three mountain

原型鏈:如下圖。

我找乙個屬性,首先會在 f.proto中去找,因為屬性值為乙個物件,那麼就會去 f.proto.proto去找,同理如果還沒找到,就會一直向上去查詢,直到結果為 null 為止。這個串起來的鏈即為原型鏈。

講到作用域,你會想到什麼?當然是執行上下文。每個函式都有自己的 excution context,和 variable object。這些環境用於儲存上下文中的變數,函式宣告,引數等。只有函式才能製造作用域。

ps:for if else 不能創造作用域。

console.log(a) ; //

undefined

var a = 1;

//可理解為

vara;

console.log(a);

//undefined

a = 1;

執行 console.log 時,a 只是被宣告出來,並沒有賦值;所以結果當然是undefined。this

本質上來說,在 js 裡 this 是乙個指向函式執行環境的指標。this 永遠指向最後呼叫它的物件,並且在執行時才能獲取值,定義是無法確認他的值。

var a =

}a.fn()

//this === a

a 呼叫了fn() 所以此時this為a

a.fn.call () //

this ===

使用call(),將this的值指定為

var fn1 =a.fn

fn1()

//this === window

雖然指定fn1 = a.fn,但是呼叫是有window呼叫,所以this 為window

this 有多種使用場景,下面我會主要介紹 4 個使用場景:

1.作為建構函式執行

function

student(name,age)

var s = new student("py1988",30)

2.作為普通函式執行

function

fn ()

fn ()

3.作為物件屬性執行

var obj =

}obj.printname ()

三個函式可以修改 this 的指向,具體請往下看:

var name = "小明" , age = "17"

var obj =

}console.log(obj.objage)

//17

obj.fun()

//安妮今年undefined

var name = "小明" , age = "17"

var obj =

}var a =

obj.fun.call(a,"蘋果","香蕉") //

jay今年23 喜歡吃蘋果不喜歡吃香蕉

jay今年23 喜歡吃蘋果不喜歡吃香蕉

obj.fun.bind(a,"蘋果","香蕉")() //

jay今年23 喜歡吃蘋果不喜歡吃香蕉

閉包閉包的概念很抽象,看下面的例子你就會理解什麼叫閉包了:

function

a();

}var c = new

a();

c.fun(); //1

c.fun();

//2

閉包就是能夠讀取其他函式內部變數的函式。在 js 中只有函式內部的子函式才能讀取區域性變數。所以可以簡單的理解為:定義在內部函式的函式。

用途主要有兩個:

1)前面提到的,讀取函式內部的變數。2)讓變數值始終保持在記憶體中。

我們先感受下非同步。

console.log("start");

settimeout(

function

() , 1000);

console.log("end");

使用非同步後,列印的順序為 start-> end->medium。因為沒有阻塞。

為什麼會產生非同步呢?

首先因為 js 為單執行緒,也就是說 cpu 同一時間只能處理乙個事務。得按順序,乙個乙個處理。

如上例所示,第一步:執行第一行列印 「start」;第二步:執行 settimeout,將其中的函式分存起來,等待時間結束後執行;第三步:執行最後一行,列印 「end」;第四部:處於空閒狀態,檢視暫存中,是否有可執行的函式;第五步:執行分存函式。

為什麼 js 引擎是單執行緒?

js 的主要用途是與使用者互動,以及操作 dom,這決定它只能是單執行緒。例:乙個執行緒要新增 dom 節點,乙個執行緒要刪減 dom 節點,容易造成分歧。

為了更好使用多 cpu,h5 提供了 web worker 標準,允許 js 建立多執行緒,但是子執行緒受到主線程控制,而且不得操作 dom。

任務列隊

單執行緒就意味著,所有的任務都要排隊,前乙個結束,才會執行後面的任務。如果列隊是因為計算量大,cpu 忙不過來,倒也算了。但是更多的時候,cpu 是閒置的,因為 io 裝置處理得很慢,例如 ajax 讀取網路資料。js 設計者便想到,主線程完全可以不管 io 裝置,將其掛起,然後執行後面的任務。等後面的任務結束掉,在反過頭來處理掛起的任務。

好,我們來梳理一下:

1)所有的同步任務都在主線程上執行,行程乙個執行棧。

2)除了主線程之外,還存在乙個任務列隊,只要一步任務有了執行結果,就在任務列隊中植入乙個時間。

3)主線程完成所有任務,就會讀取列隊任務,並將其執行。

4)重複上面三步。

只要主線程空了,就會讀取任務列隊,這就是 js 的執行機制,也被稱為 event loop(事件迴圈)。

壓在redis身上的三座大山

三座大山分別是快取穿透,快取擊穿,快取雪崩 快取穿透 查詢引數是無效的key,這個key在redis沒有,然後取資料庫查也查不到,導致無用查詢。解決方法有兩個 1是value設定成null。2是使用布隆過濾器,布隆過濾器可以看出乙個陣列,然後我們對key進行多次不同hash運算,然後對長度取模,對應...

JS三座大山再學習 一 原型和原型鏈

本文已發布在西瓜君的個人部落格,原文傳送門 西瓜君之前學習了js的基礎知識與三座大山,但之後工作中沒怎麼用,印象不太深刻,這次打算再重學一下,打牢基礎。衝鴨 js實現繼承的方式是通過原型和原型鏈實現的,js中沒有類 此處指es5,es6中加上了class語法糖 每個函式都有prototype 原型 ...

服裝企業搞資訊化前面的「三座大山」

服裝行業作為中國具有世界競爭力的行業之一,其領先地位在很大程度上得益於國內極為低廉的勞動力成本優勢。但隨著近年來國內物價的不斷 當勞動力成本優勢逐漸喪失的時候,如何在管理模式和資訊化應用方面進行創新就成為了擺在我們面前的問題。但由於國內服裝企業在對資訊化應用的認識以及人才 技術等方面還普遍存在瓶頸,...