フロントエンド 30 Q: 30 歳で立っていられますか

ここに画像の説明を挿入

序文:

      金3銀4、仕事の調整中なら、ブックマークすることをお勧めします。これは、インターネットの寒い冬を防ぐための必須のガイドです〜

1. 出力結果は何ですか? サイクル 1 の出力結果をサイクル 2 の印刷結果に変更する方法

for(var i = 0;i<5;i++){
    
    
  setTimeout(()=>{
    
    
    console.log(i) //五次5
  },1000)
  console.log(i) //0 1 2 3 4
}
for(let i = 0;i<5;i++){
    
    
  setTimeout(()=>{
    
    
    console.log(i) // 0 1 2 3 4
  },1000)
}
// 改变
for(var i = 0;i<5;i++){
    
    
  (function(j) {
    
    
      setTimeout( function timer() {
    
    
          console.log( j );
      }, j*1000 );
  })(i);
}

      これは setTimeout が非同期で実行されるためで、SetTimeout は for ループごとに 1 回実行されますが、内部の関数は実行されず、タスク キューに配置されて実行されます。タスクキュー内のタスクは、メインラインのタスクが実行された後にのみ実行されます。つまり、for ループの実行が終了するまで待ってから fun 関数を実行しますが、for ループが終了すると i の値が 5 に変更されるため、タイマーは 5 秒間実行されますが、コンソール まだ5。
同時に、for ループの先頭にある let は i を for ループにバインドするだけでなく、実際には i をループ本体の各反復に再バインドし、前の反復の最後の値が確実に再割り当てされるようにします。 。setTimeout の function() は新しいドメインに属します。var で定義された変数は、関数実行ドメインに渡すことはできません。let を使用して宣言することで、ブロック変数がこのブロックに作用できるため、関数は変数 i を使用できます。この無名関数のスコープは、この点を利用して行われる for パラメーターのスコープとは異なります。この匿名関数のスコープは、内部メソッドで使用できるクラスの属性に似ています。
最後に、var を使用して宣言された変数には変数の昇格の問題が発生しますが、let を使用した場合には変数の昇格の問題は発生しません。ループヘッダーとして var を使用する必要がある場合、ループ後の出力結果はまったく同じになります。パラメーターまたはクロージャーを渡す方法を使用できます。

2. 配列ループメソッドとは何ですか?

(1)、forEach: 配列を走査します。戻り値はありません。ループ本体に return を記述することはできません。元の配列の内容が変更されます。forEach() はオブジェクト (2) をループすることもできます。 )、map: 配列を走査し、新しい配列を返します
。元の配列の内容は変更しません
(3)、filter: 配列内の条件を満たさない要素をフィルターで除外し、条件を満たす要素を配置します。元の配列を変更せずに条件を新しい配列に代入し
(4)、以下を削減します。

let array = [1, 2, 3, 4];
let temp = array.reduce((x, y) => {
    
    
	console.log("x,"+x);
	console.log("y,"+y);
	console.log("x+y,",Number(x)+Number(y));
	return x + y;
});
console.log(temp);  // 10
console.log(array);  // [1, 2, 3, 4]

(5)、every: 配列を走査し、各項目が true の場合は true を返し、1 つが false である限り false を返します (
6)、some: 配列の各項目を走査し、1 つが true を返した場合はループを停止します

3. script タグの defer と async の違いは何ですか?

defer : スクリプトは非同期で読み込まれた後、すぐには実行されませんが、ページ全体がメモリ内で通常にレンダリングされるまで実行されません。複数の遅延スクリプトは、ページに表示される順序でロードされます。
async : スクリプトも非同期でロードします。違いは、スクリプトがロード直後に実行されることです。これにより、 async 属性の下にあるスクリプトの順序が狂います。これは、スクリプトに逐次的な依存関係がある場合には当てはまりません。

4. setTimeout() メソッドを使用して setInterval() をシミュレートする場合と setInterval() を使用する場合の違いは何ですか?

      まず setInterval の欠点を見てください。setInterval() を使用して作成されたタイマーは、タイマー コードが定期的にキューに挿入されることを保証します。このアプローチの問題は、コードが再びキューに追加される前にタイマー コードの実行が完了しない場合、タイマー コードが間隔をあけずに連続して数回実行されることです。

      そのため、現在の実行スタックの実行に時間がかかり、イベント キューに複数のタイマーによって追加されたイベントが蓄積され、実行スタックが終了すると、これらのイベントが一時停止することなく順番に実行されるという状況が発生する可能性があります。間隔をあけて実行することによる効果。

      ただし幸いなことに、JavaScript エンジンはこの問題を回避できるほど賢いものです。setInterval() を使用する場合、タイマー コードは、そのタイマーのコード インスタンスが他にない場合にのみキューに追加されます。これにより、タイマー コードが指定された時間の最小間隔をキューに入れることが保証されます。この繰り返しタイマー ルールには 2 つの問題があります:

1. 一部の間隔がスキップされる;

2. 複数のタイマーのコード実行時間が予想よりも短くなる可能性がある;

例: onclick イベント ハンドラーが setInterval() を使用して 200 ミリ秒を設定するとします。リピートタイマー。
イベント ハンドラーが完了するまでに 300 ミリ秒強かかる場合。
ここに画像の説明を挿入


       注: この例の最初のタイマーは 205 ミリ秒でキューに追加されますが、300 ミリ秒が経過するまで実行できません。タイマー コードが実行されると、405 ミリ秒で別のコピーがキューに追加されます。次の間隔 (605 ミリ秒) では、最初のタイマー コードはまだ実行されていますが、キューにはタイマー コードのインスタンスがすでに存在します。その結果、この時点のタイマー コードはキューに追加されません。その結果、5msに追加されたタイマーコードが終了すると、すぐに405msに追加されたタイマーコードが実行されます。

       したがって、代わりに setTimeout を使用すると、1 つのイベントが終了した後にのみ次のタイマー イベントがトリガーされるようにすることができます。これにより、タイマー コードが指定された間隔で最小間隔をキューに入れることが保証されます。
これを行うための 2 つの簡単な方法を次に示します。

function say(){
    
     
  //something 
  setTimeout(say,200); 
}
setTimeout(say,200) 

// 或者

setTimeout(function(){
    
     
  //do something 
  setTimeout(arguments.callee,200); 
},200); 

5. JS は一度に 1 枚の画像の読み込みをどのように制御し、読み込み後に次の画像を読み込みますか

(1) 方法1

<script type="text/javascript"> 
  var obj=new Image(); 
	obj.src="http://www.phpernote.com/uploadfiles/editor/201107240502201179.jpg"; 
	obj.onload=function(){
    
     
  	alert('图片的宽度为:'+obj.width+';图片的高度为:'+obj.height); 
  	document.getElementById("mypic").innnerHTML="<img src='"+this.src+"' />"; 
	}
</script> 

<div id="mypic">onloading……</div> 

(2) 方法2

<script type="text/javascript"> 
  var obj=new Image(); 
	obj.src="http://www.phpernote.com/uploadfiles/editor/201107240502201179.jpg"; 
	obj.onreadystatechange=function(){
    
     
  if(this.readyState=="complete"){
    
     
    alert('图片的宽度为:'+obj.width+';图片的高度为:'+obj.height); 
    document.getElementById("mypic").innnerHTML="<img src='"+this.src+"' />"; 
    }
  }
</script> 

  <div id="mypic">onloading……</div> 

6. 睡眠の効果を実現する方法 (es5 または es6)

(1) whileループのやり方

function sleep(ms){
    
     
  var start=Date.now(),expire=start+ms; 
  while(Date.now()<expire); 
  console.log('1111'); 
  return; 
}

sleep(1000)を実行後、1000msスリープ後に1111が出力されます。上記の循環方式の欠点は明らかで、無限ループを引き起こしやすいです。
(2) 約束による実現

function sleep(ms){
    
     
  var temple=new Promise( 
    (resolve)=>{
    
     
      console.log(111);
      setTimeout(resolve,ms);
    }); 
  return temple 
}

sleep(500).then(
  function(){
    
    
    //console.log(222) 
})

//最初に111を出力し、500ms遅れて222を出力
(3) asyncでカプセル化

function sleep(ms){
    
     
  return new Promise((resolve)=>setTimeout(resolve,ms)); 
}
async function test(){
    
     
  var temple=await sleep(1000); 
  console.log(1111) 
  return temple 
}
test(); 

//遅延 1000ms、出力 1111
(4).generate で実現

function* sleep(ms){
    
     
  yield new Promise(function(resolve,reject){
    
     
    console.log(111); 
    setTimeout(resolve,ms); 
  })
}

sleep(500).next().value.then(
  function(){
    
    
    console.log(2222)
}) 

7. JS内のすべてのオブジェクト(ラッパーオブジェクト、日付オブジェクト、通常オブジェクト)のディープクローン作成を実現します。

       オブジェクトのディープ クローン作成は再帰によって簡単に実現できますが、この方法が ES6 で実装されるか ES5 で実装されるかにかかわらず、同じ欠陥があります。つまり、特定のオブジェクト (配列や関数など) のディープ コピーのみを実現でき、実現することはできません。パッケージ化オブジェクト Number. String、Boolean、Date オブジェクト、RegExp オブジェクトのコピーを実現します。
(1) 従来の方法

function deepClone(obj){
    
     
  var newObj= obj instanceof Array?[]:{
    
    }; 
  for(var i in obj){
    
     
    newObj[i] = typeof obj[i] == 'object' ? deepClone(obj[i]):obj[i]; 
  }
  return newObj; 
}

このメソッドは、次のような一般オブジェクトと配列オブジェクトのクローン作成を実現できます。

var arr=[1,2,3]; 
var newArr=deepClone(arr); 
// newArr->[1,2,3] 
var obj={
    
     
  x:1, 
  y:2 
}
var newObj=deepClone(obj); 
// newObj={x:1,y:2} 


ただし、次のような Number、String、Boolean オブジェクト、および通常のオブジェクト RegExp および Date オブジェクトなどのパッケージ化オブジェクトの複製を実現することはできません。

//Number 包装对象 
var num=new Number(1); 
typeof num // "object" 
var newNum=deepClone(num); 
//newNum -> {} 空对象 

//String 包装对象 
var str=new String("hello"); 
typeof str //"object" 
var newStr=deepClone(str); 
//newStr-> {0:'h',1:'e',2:'l',3:'l',4:'o'}; 

//Boolean 包装对象 
var bol=new Boolean(true); 
typeof bol //"object" 
var newBol=deepClone(bol); 
// newBol ->{} 空对象  

(2) valueof() 関数

       すべてのオブジェクトには valueOf メソッドがあり、元の値がある場合、そのオブジェクトをデフォルトでそれを表す元の値に変換します。オブジェクトは複合値であり、ほとんどのオブジェクトは実際にはプリミティブ値として表すことができないため、デフォルトの valueOf() メソッドはプリミティブ値を返すのではなく、単純にオブジェクト自体を返します。配列、関数、および正規表現は単にこのデフォルト メソッドを継承し、これらの型のインスタンスで valueOf() メソッドを呼び出すと、単純にオブジェクト自体が返されます。
プリミティブ値またはラッパー クラスの場合:

function baseClone(base){
    
     
  return base.valueOf(); 
}

//Number 
var num=new Number(1); 
var newNum=baseClone(num); 
//newNum->1 

//String 
var str=new String('hello'); 
var newStr=baseClone(str); 
// newStr->"hello" 

//Boolean 
var bol=new Boolean(true); 
var newBol=baseClone(bol); 
//newBol-> true 

実際、クラスをパッケージ化する場合、= 記号を使用してクローンを作成できます。実際、ディープ クローン作成などというものはありません。ここでは、valueOf を使用して実装しており、文法的に準拠しています。
Date 型の場合:
valueOf メソッドのため、Date クラスで定義された valueOf() メソッドはその内部表現、つまり 1970 年 1 月 1 日からのミリ秒数を返します。 したがって、Date プロトタイプで clone メソッドを定義できます。

Date.prototype.clone=function(){
    
     
  return new Date(this.valueOf()); 
}
var date=new Date('2010'); 
var newDate=date.clone(); 
// newDate-> Fri Jan 01 2010 08:00:00 GMT+0800 

通常のオブジェクト RegExp の場合:

RegExp.prototype.clone = function() {
    
     
  var pattern = this.valueOf(); 
  var flags = ''; 
  flags += pattern.global ? 'g' : ''; 
  flags += pattern.ignoreCase ? 'i' : ''; 
  flags += pattern.multiline ? 'm' : ''; 
  return new RegExp(pattern.source, flags); 
};
var reg=new RegExp('/111/'); 
var newReg=reg.clone(); 
//newReg-> /\/111\// 

8. JS はオブジェクトのプロパティの変更をリッスンします

ここではユーザーオブジェクトがあると仮定します。
(1) ES5 では、Object.defineProperty を使用して既存のプロパティの監視を実現できます。

Object.defineProperty(user,'name',{
    
     
	setfunction(key,value){
    
    }
})
//缺点:如果 id 不在 user 对象中,则不能监听 id 的变化

(2) ES6ではProxy経由で実現可能

var user = new Proxy({
    
    }{
    
     
	setfunction(target,key,value,receiver){
    
    }
})
//这样即使有属性在 user 中不存在,通过 user.id 来定义也同样可以这样监听这个属性的变化 

9. Vue3.0 では、defineProperty API の代わりに Proxy API を使用するのはなぜですか?

A: レスポンシブな最適化。
(1)defineProperty API の制限の最大の理由は、この API がシングルトン プロパティしか監視できないことです。
Vue2.x の応答性の高い実装は、defineProperty の記述子に基づいており、データ内の属性をトラバース + 再帰し、各属性のゲッターとセッターを設定します。
これが、Vue がデータ内の事前定義された属性にのみ応答できる理由です。Vue で添字を使用して属性の値を直接変更したり、既存のオブジェクト属性を追加したりすることは、セッターでは監視できません。これは、defineProperty の制限です。
(2) プロキシ API の監視は、すべての属性を完全にプロキシできるオブジェクトを対象としています。
プロキシ API はオブジェクトをリッスンし、このオブジェクトに対するすべての操作が監視操作に入り、すべての属性が完全にプロキシされるようになります。ターゲット オブジェクトの前に「インターセプト」の層が設定され、外部アクセスが行われることがわかります。このインターセプト層を通じて、外部アクセスをフィルタリングして書き換えるメカニズムが提供され、パフォーマンスが大幅に向上し、コードが改善されます。
(3) 応答性が遅い
Vue.js 2.x では、プロパティのネストが深いオブジェクトの場合、その内部の深い変更をハイジャックしたい場合、オブジェクトを再帰的に走査し、Object.defineProperty を実行して各層のオブジェクト データを変換する必要があります。応答性が高くなり、間違いなく大量のパフォーマンスが消費されます。
Vue.js 3.0 では、Proxy API を使用するとオブジェクト内部の深いレベルのプロパティの変更を監視できないため、getter で再帰的に応答する処理方法となり、実際にアクセスされる内部プロパティが Responsive になるという利点があります。 、単にオンデマンドに応答し、パフォーマンスの消費を削減すると言えます。

10. jsのマクロタスク、マイクロタスク、サイクル機構の理解

jsはシングルスレッドに属し、同期と非同期に分けられます. jsのコードは上から下へ実行されます. 同期タスクは単純な論理演算や関数などメインスレッドですぐに実行されますが、非同期タスクはすぐには実行されません,ただし、移動されます。ステップは、ajax、Promise、イベント、タイマーなどの非同期キューに配置されます。
最初に同期を実行し、メインスレッドの終了後に非同期の順序で再度実行します。
イベントサイクル: 同期タスクがメインスレッドに入り、すぐに実行され、実行後、非同期タスクがメインスレッドに入り、このサイクルが発生します。
イベントループでは、各サイクルの動作をティックと呼びますが、ティックのタスク処理モデルは比較的複雑で、マクロタスク(マクロタスク)とマイクロタスク(マイクロタスク)のマクロタスクとマイクロタスク(実行)の2つの言葉が存在します
。最初にマイクロタスク、次にマクロタスク)
js
マクロタスクの場合: setTimeOut、setTimeInterval、postMessage
マイクロタスク: Promise.then
フォーカス: Promise 同期 Promise.then 非同期

console.log("开始111");

setTimeout(function() {
    
    

  console.log("setTimeout111");

}, 0);

Promise.resolve().then(function() {
    
    

  console.log("promise111");

}).then(function() {
    
    

  console.log("promise222");

});

console.log("开始222");

次の手順に従って分析してみましょう。
1. 同期タスクが発生したら、最初に「Start 111」を出力します。
2. 非同期の setTimeout が発生した場合は、それをキューに入れて実行を待ちます。
3. Promise が見つかったら、それを待機キューに入れます。
4. 同期タスクが発生した場合は、「Start 222」を直接出力します。
5. 同期実行後、実行キューのコードに戻って上から順に実行しますが、マクロタスクsetTimeoutとマイクロタスクPromiseがある場合は、マイクロタスクを先に実行してからマクロタスクを実行します。
したがって、印刷の順序は、start111、start222、promise111、promise222、setTimeout111 になります。

11.RGBと16進数の色変換

まず第一に、RGB と 16 進数の関係を知る必要があります。たとえば、最も一般的な白色 RGB は rgb(255, 255, 255) と表現され、16 進数は #FFFFFFF と表現されます。16 進数の色を含めることができます。 「#」の場合、FF、FF、FFの2つに分かれていますが、16進数のFFを10進数に換算するといくらになるでしょうか?そうです、255です!

16 進数と RGB の関係を理解すると、RGB を 16 進数に変換する方法が非常に簡単であることがわかります。

3 つの RGB 値を 16 進数に変換して連結します。つまり、rgb(255, 255, 255) => '#' + 'FF' + 'FF' + 'FF' となります。
左シフトを賢く使用すると、16 進数値の部分を整数、つまり FFFFFF として扱います。上で説明したように、左シフトが 16 進数の計算に基づいている場合は、FF0000 + FF00 + FF として理解できます。は FF << 4, FF << 2, FF ですが、実際にバイナリに変換すると、次のように FF << 16 になります。

x * 16^4 = x * 2 ^ 16

原理を理解した後のコードは次のようになります。

function RGBFUN(rgb){
    
    
    // 取出rgb中的数值
    let arr = rgb.match(/\d+/g);
    console.log(arr,'输出rgb转换数值') //[ '0', '255', '0' ] 输出rgb转换数值
    if (!arr || arr.length !== 3) {
    
    
        console.error('rgb数值不合法');
        return
    }
    let hex = (arr[0]<<16 | arr[1]<<8 | arr[2]).toString(16);
    // 自动补全第一位
    if (hex.length < 6) {
    
    
        hex = '0' + hex;
    }
    console.log(`#${
      
      hex}`,'输出转换之后的数值') // #0ff00 输出转换之后的数值
    return `#${
      
      hex}`;
}
RGBFUN('rgb(0,255,0)')

12. JavaScript ビット演算: 2 つのオペランドの対応するビットに 1 が 1 つだけある場合、結果は 1 になり、それ以外の場合は 0 になります。

簡易暗号化が実現可能

const value = 456;
function encryption(str) {
    
    
    let s = '';
    str.split('').map(item => {
    
    
    s += handle(item);
    })
    return s;
}

function decryption(str) {
    
    
let s = '';
str.split('').map(item => {
    
    
    s += handle(item);
})
return s;
}

function handle(str) {
    
    
    if (/\d/.test(str)) {
    
    
    return str ^ value;
    } else {
    
    
    let code = str.charCodeAt();
    let newCode = code ^ value;
    return String.fromCharCode(newCode);
    }
}

let init = 'JS 掌握 位运算';
let result = encryption(init);             // ƂƛǨ扄戩Ǩ亅踘穟 加密之后
console.log(result,'加密之后')
let decodeResult = decryption(result);     // JS 掌握 位运算 解密之后
console.log(decodeResult,'解密之后')

13. [Webpack ベース] どのようなローダーがありますか? どちらを使用したことがありますか?

書類

  • val-loader : コードをモジュールとして実行し、JS コードとしてエクスポートします。
  • ref-loader : ファイル間の依存関係を手動で確立するために使用されます

JSON

  • cson-loader : CSON ファイルのロードと変換

構文変換

  • babel-loader : ES2015+ コードを Babel でロードし、ES5 にトランスパイルします。
  • esbuild-loader : ES2015+ コードをロードし、esbuild を使用して ES6+ にトランスパイルします。
  • buble-loader : Bublé で ES2015+ コードをロードし、ES5 にトランスパイルします。
  • traceur-loader : Traceur を使用して ES2015+ コードをロードし、ES5 に変換します
  • ts-loader : TypeScript 2.0以降をJavaScriptのようにロードします
  • Coffee-loader : JavaScript のように CoffeeScript をロードします
  • fengari-loader : fengari を使用して Lua コードをロードします
  • elm-webpack-loader : Elm を JavaScript のようにロードします

テンプレート

  • html-loader : HTML を文字列としてエクスポートするには、静的リソースの参照パスを渡す必要があります。
  • pug-loader : Pug および Jade テンプレートをロードし、関数を返します
  • markdown-loader : Markdown を HTML にコンパイルします
  • act-markdown-loader : markdown-parse パーサーを使用して Markdown を React コンポーネントにコンパイルします
  • posthtml-loader : PostHTML を使用して HTML ファイルを読み込み、変換します
  • handlebars-loader : Handlebars ファイルを HTML にコンパイルします
  • markup-inline-loader : SVG/MathML ファイルを HTML にインライン化します。これは、アイコン フォントや CSS アニメーションを SVG に適用するときに便利です。
  • twig-loader : Twig テンプレートをコンパイルし、関数を返します
  • mark-loader : リマークを通じてマークダウンをロードし、コンテンツ内の画像の解析をサポートします。

スタイル

  • style-loader : モジュールによってエクスポートされたコンテンツをスタイルとして追加し、DOM に追加します。
  • css-loader : CSS ファイルをロードし、インポートされた CSS ファイルを解析し、最後に CSS コードを返します。
  • less-loader : LESS ファイルをロードしてコンパイルします
  • sass-loader : SASS/SCSS ファイルをロードしてコンパイルします。
  • postcss-loader : PostCSS を使用して CSS/SSS ファイルをロードおよび変換する
  • stylus-loader : Stylus ファイルをロードしてコンパイルします

フレーム

  • vue-loader : Vue コンポーネントをロードしてコンパイルします
  • angular2-template-loader : Angular コンポーネントをロードしてコンパイルします

14. Js が継承をどのように実装するかについて話しますか?

1. プロトタイプ チェーンの継承: 親クラスのインスタンスをサブクラスのプロトタイプとして使用します。
利点:
1. シンプルで実装が簡単です
。2. 親クラスは新しいプロトタイプ メソッドとプロトタイプ属性を追加し、サブクラスはそれらにアクセスできます。
欠点:
1. プロトタイプは一度に 1 つのインスタンスによってのみ変更できるため、多重継承は実装できません。
2. プロトタイプ オブジェクトのすべてのプロパティはすべてのインスタンスによって共有されます (アピール例の color プロパティ)
3. サブクラス インスタンスを作成するとき、親クラスのコンストラクタにパラメータを渡すことはできません。


2. コンストラクタの継承:親クラスのインスタンス属性をサブクラスにコピーします。
利点:
1. プロトタイプチェーン継承において、サブクラスのインスタンスが親クラスの参照属性を共有する問題を解決します。
2.サブクラスのインスタンス作成時に親クラスにパラメータを渡すことができる
3. 多重継承が実現できる(親クラスのオブジェクトを複数呼び出す)
デメリット:
1. インスタンスは親クラスのインスタンスではなく、サブクラスのインスタンスである
2 . 親クラスのインスタンスのプロパティとメソッドのみを継承できますが、そのプロトタイプのプロパティとメソッドは継承できません 3. 関数の
再利用を実現するために、各サブクラスは親クラスのインスタンス関数のコピーを持つため、パフォーマンスに影響します3.


結合継承 (クラシック継承): プロトタイプ チェーンと借用コンストラクターのテクノロジを結合します。プロトタイプチェーンを使用してプロトタイプのプロパティとメソッドの継承を実現し、コンストラクターを使用してインスタンスのプロパティの継承を実現します 利点: 1. 構築継承の欠点を補い、インスタンスのプロパティ

メソッドとプロトタイプの両方を継承できるようになりましたプロパティとメソッド
2. サブクラスのインスタンスであり、親クラスのインスタンスでもある
3. 親クラスにパラメータを渡すことができる
4. 関数は再利用できる
欠点:
1. 親クラスのコンストラクターが 2 回呼び出されます。 2 つのインスタンスが生成されます
2. コンストラクターは質問4. インスタンスの継承:


親クラスのインスタンスに新しい
機能を追加し、それをサブクラスのインスタンスとして返す
欠点
:
1. インスタンスは親クラスのインスタンスであり、サブクラスのインスタンスではありません
2.多重継承はサポートしません。


5. 継承のコピー: 親クラスのインスタンスのメソッドとプロパティをサブクラスのプロトタイプにコピーします。
利点:
1. サポート 多重継承の欠点
:
1. 効率が低く、パフォーマンスが低く、メモリ使用量が多くなります (理由:親クラスのプロパティをコピーする必要があります)
2. 親クラスの非列挙メソッドを取得できません (非列挙メソッドには for-in を使用してアクセスできません)


6 . 寄生組み合わせ継承: 寄生メソッドを通じて、インスタンスは親クラスの属性が切り取られるため、継承の組み合わせによって 2 つのインスタンスを生成するという
欠点回避されます。実装されている) Object.create によって簡略化されている) 7.es6 – クラス継承: extends を使用してどの親クラスから継承するかを示し、super をサブクラス コンストラクターで呼び出す必要があります。利点: 1. 構文はシンプルで理解しやすいです。操作がより便利になります欠点: 1. すべてのブラウザがクラス キーワード lass Per をサポートしているわけではありません。












15. 最終的な結果はどのように出力されますか?

var length = 10;
function fn(){
    
    
    console.log(this.length)
}
var obj = {
    
    
    length: 5,
    method: function(fn){
    
    
        fn();
        arguments[0]()
    }
}
obj.method(fn,1)			//10  2

分析:
1. fn() : アロー以外の関数が関数内にネストされている場合、この時点で、ネストされた関数内の this が指定されていない場合は、 window オブジェクトを指す必要があるため、ここで fn を実行すると window が出力されます。長さlet を使用して変数を宣言すると、ブロックレベルのアクションが形成され、変数の昇格はありませんが、var には宣言の昇格があります。したがって、出力結果は 10; ですが、let length = 10 ; の場合、出力結果は 0 2 となります。
2.引数0 : メソッド呼び出し(オブジェクトの属性が関数の場合、この属性をメソッドと呼び、この属性を呼び出すことをメソッド呼び出しと呼びます)では、関数本体が実行されると、オブジェクトと配列が属性アクセスの対象は、呼び出しメソッド内の this のポインタになります。(平たく言えば、これが指すメソッドを呼び出す人)。
ここで、引数0は fn を呼び出す引数オブジェクトの属性 [0] として使用されるため、fn の this は属性アクセス主体のオブジェクト引数を指します。
ここでもう 1 つ注意すべき点は、arguments パラメーターは関数のすべての実パラメーターを参照し、仮パラメーターとは何の関係もないことです。つまり、関数が呼び出されるとき、渡された実際のパラメータ fn と 1 はパラメータとして引数オブジェクトに格納されるため、引数の長さは 2 であるため、2 が出力されます。

16. CLI を実装してテンプレート プロジェクトを作成するにはどうすればよいですか?

実装の基本的な手順を説明します。

  1. 端子パラメータ解析
  2. CLI は、プロジェクトの作成に必要なパラメータを対話的に収集します。
  3. テンプレートプロジェクトをコピー
  4. package.jsonファイルを書き換える(プロジェクト名などを変更する)
  5. 作成完了後にプロジェクトの初期化プロセスを要求または実行する
  6. 実装プロセスに関する注意事項:
  7. package.json 内の名前の命名規則
  8. 同名のプロジェクトを再度作成する場合は、上書きするか中断するかを考慮する必要があり、上書きする場合は作成したプロジェクトがバージョン管理に接続されているかどうかを考慮する必要がある
  9. 作成完了後、プロジェクトの初期化を促すか実行するかは、使用する際のパッケージマネージャーに応じて判断してください。
  10. コンテンツの拡張
  11. CLI の対話型パラメーターのコレクションは、過去のプロジェクト テンプレートまたはサードパーティのテンプレートをサポートし、対応するテンプレートの作成を通じて互換性を実現できます。
  12. CLI を使用してプロジェクトを作成するには、通常、最初に CLI をインストールするコマンドを実行し、次に組み込みコマンドを実行して 2 つのステップでプロジェクトを作成する必要があります。命名規則を使用して npm create xxx を直接実行することを検討できます。 、yarn create xxx で CLI を開始し、プロジェクトを作成します

17. 自動追跡を実現するにはどうすればよいですか?

自動埋め込みでは、Babel + カスタム埋め込みプラグインを使用して、プロジェクトのコンパイル中に関数のインストルメンテーションを自動化できます。Babel の自動インストルメンテーションを使用する際に注意すべき点が 2 つあります。

  1. 埋め込みポイント モジュールは、インポートされているかどうか、およびインポート方法を判断します。
    1. Babel プラグインの実行時に、ImportDeclarationコードを走査することによって、指定された組み込みモジュールが含まれているかどうかを分析します。
    2. 埋め込まれたモジュールのインポートは、 Babel 組み込み@babel/helper-module-importsモジュールを通じて実現されます。
  2. 埋め込みポイント関数を生成してソース関数に挿入する方法。
    1. 生成方法:template.statement組み込み API を通じて組み込み関数を呼び出す AST を生成します。
    2. 挿入方法: さまざまな形式の関数に対応する AST の型にはClassMethodArrowFunctionExpression、 、FunctionExpressionFunctionDeclaration含まれており、Babel がそれらをトラバースするときに、生成された AST を対応するノードの本体に挿入します。関数本体のない関数を追加する必要がある場合、および処理された戻り値。

18. JSON Web Tokenについて教えてください。

  1. 動作原理:
    サーバー認証後、JWT はユーザー情報、時刻、セキュリティ情報などを含む JSON オブジェクトを生成して、現在のユーザーのステータスを一意に表し、その後のデータ インタラクションで引き続きそのオブジェクトを保持し、リクエストの有効性を示します。

  2. データ構造:
    JWTはヘッダー、ペイロード、署名を「.」で繋いだ文字列であり、JWT文字列中に改行はありません

  3. header は、メタデータを記述するために使用される JSON オブジェクトです。

  4. ペイロードの形式要件はヘッダーの要件と同じで、コンテンツには主にビジネス シナリオのニーズを満たす公式定義フィールド + カスタム フィールドが含まれます。

  5. 「ヘッダー」も「ペイロード」も暗号化については言及しておらず、単なる文字のエンコードであるため、ユーザー関連のセキュリティ関連情報を「ヘッダー」と「ペイロード」に配置すべきではありません。これによって上記 2 つのブロックが妨げられることはありません。 of は仲介者によって傍受され、改ざんされるため、「署名」が必要です。

signature = HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)
  1. 利用方法:
    HTTPヘッダにキーを「Authorization」、値を「Bearer」とした情報の集合を追加するのが標準的な利用方法であり、トークンの具体的な格納方法は業務に応じて対応されます。
    4. 注意事項:

  2. JWT はデフォルトでは暗号化されませんが、JWT 自体を暗号化することもできます。

  3. デフォルトで暗号化されていない場合は、機密データを JWT に入れないでください。

  4. 中間者攻撃を防ぐために HTTPS を推奨します。

19. JavaScript の toString() と join() の違いは何ですか?

// 声明两个不同的数组
const fruitList = ['苹果', '香蕉', '百香果']
const objList = [
  {
    
    
    name: '张三',
    age: 16
  },
  {
    
    
    name: '李斯',
    age: 18    
  }
]
// 通过toString()直接进行转换为字符串
console.log(fruitList.toString()) // '苹果,香蕉,百香果'
console.log(objList.toString()) // '[object Object],[object Object]'

// 通过join()自定义拼接进行转换为字符串
console.log(fruitList.join()) // '苹果,香蕉,百香果'
console.log(fruitList.join(',')) // '苹果,香蕉,百香果'
console.log(fruitList.join('、')) // '苹果、香蕉、百香果'
console.log(fruitList.join('分割')) // '苹果分割香蕉分割百香果'
console.log(objList.join()) // '[object Object],[object Object]'

要約:
toString() と join() は、配列内のすべての要素を文字列に入れます。
join() 関数の内部パラメータが空の場合、join() は toString() と同等です。
join(',') 関数の内部パラメータがカンマ文字である場合、配列がカンマで区切られていることを意味します。これは、内部パラメータが空であることと同等です。
join(',') 関数の内部パラメータがカンマ文字の場合、配列がカンマで区切られていることを意味します。
join('split') 関数の内部パラメータが文字列の場合、'split' 文字列を使用して配列を分割することを意味します。

20. null / unknownの違い

Null 値: null 型に属し、「null 値」を表し、空のオブジェクト ポインターを表します。typeof 操作を使用して「object」を取得するため、特別なオブジェクト値として考えることができます。
未定義値:未定義型に属し、宣言した変数を初期化せずに代入した場合、結果は不定になります。typeof 操作を使用して「未定義」を取得します。

21.map() と forEach() によるループの違いは何ですか?

array.map(function(currentValue, index, arr), thisValue)
const nums = [4, 9, 16, 25]
const emptyList = []
const doubleNums = nums.map(Math.sqrt)

console.log(doubleNums) // [2, 3, 4, 5]
console.log(nums) // [4, 9, 16, 25]
console.log(emptyList.map(Math.sqrt)) // []

定義と使用法:
map() メソッドは新しい配列を返し、配列内の要素は元の配列要素に対して関数を呼び出すことによって処理された値です。
map() メソッドは、元の配列要素の順序で要素を順番に処理します。
map() は空の配列をチェックしません。
map() は元の配列を変更しません。

array.forEach(function(currentValue, index, arr), thisValue)
const nums = [4, 9, 16, 25]
const emptyList = []
const doubleNums = nums.forEach(Math.sqrt)

console.log(doubleNums) // undefined
console.log(emptyList.forEach(Math.sqrt)) // undefined

定義と使用法:
forEach() メソッドは、配列の各要素を呼び出し、その要素をコールバック関数に渡すために使用されます。
forEach() は空の配列に対してコールバック関数を実行しません。
違い:
forEach() メソッドは実行結果を返しませんが、未定義です。つまり、forEach() は元の配列を変更します。map() メソッドは新しい配列を取得して返します。
map() は新しい配列を格納するためにメモリ領域を割り当てて戻りますが、forEach() はデータを返しません。
forEach() を使用すると、コールバックで元の配列の要素を変更できます。map() は新しい配列を返します。

22. for/in と for/of の違いは何ですか?

Array.prototype.method = function () {
    
    }
let myArray = [1, 2, 3]
myArray.name = '数组';

for (let index in myArray) {
    
    
  console.log(index) // 0,1,2, name, method
  console.log(myArray[index]) //1,2,3,数组,f() {}
}

for (let val of myArray) {
    
    
  console.log(val) // 1,2,3
}

最も直接的な違いは、for/in は配列のインデックスを走査するのに対し、 for/of は配列要素の value を走査することです
for/in トラバーサルの欠陥:

  1. インデックスは文字列型の数値であるため、幾何学的演算を直接実行することはできません
  2. 走査順序は実際の内部順序ではない可能性があります
  3. for/in は、プロトタイプを含む、配列の列挙可能なすべてのプロパティを反復処理します。

したがって、通常は配列ではなくオブジェクトを走査するために使用されます。
for/of トラバーサルの欠点:
for/of は通常のオブジェクトをサポートしていません。オブジェクトのプロパティをトラバースしたい場合は、for/in ループ、または組み込みの Object.keys() メソッド: Object を使用できます
。オブジェクトのインスタンス プロパティを取得するkeys(obj) プロトタイプのメソッドとプロパティを除くコンポーネントの配列

for(let key of Object.keys(obj)) {
    
    
  console.log(key + ":" + Object[key])
}

for/of ステートメントは、反復可能なオブジェクトを反復するループを作成し、配列、文​​字列、マップ、セットなどの反復データ構造を走査できるようにします。

// variable 每个迭代的属性值被分配给该变量。
// iterable 一个具有可枚举属性并且可以迭代的对象。
for(let variable of iterable) {
    
    
  statement
}

一般に、for/in はオブジェクトを走査し、for/of は配列を走査します。

23. CSS のレンダリング レイヤーの構成は何ですか。ブラウザはどのようにして新しいレンダリング レイヤーを作成しますか?

DOM ツリーの各ノードは描画オブジェクト (RenderObject) に対応し、それらの描画オブジェクトが同じ座標空間 (Z 軸空間) にあるとき、RenderLayers、つまり描画レイヤーが形成されます。レンダリングレイヤーは、ページ要素が正しい順序で積み重ねられることを保証しますが、このとき、透明要素と重複要素の表示を正しく処理するために、レイヤー構成 (コンポジット) が表示されます。このプロセスは、レイヤーが間違った順序で結合されると要素が異常に表示されるため、要素が重なっているページでは特に重要です。

ブラウザが新しいレンダリング レイヤーを作成する方法

  • ルート要素ドキュメント
  • 明確な位置決め属性 (相対、固定、固定、絶対) を持つ
  • 不透明度 < 1
  • CSSフィルタープロパティあり
  • CSSマスクプロパティを持つ
  • CSS mix-blend-mode プロパティがあり、その値が正常ではありません
  • CSS 変換プロパティがあり、その値は none ではありません
  • backface-visibility プロパティは非表示です
  • CSSリフレクションプロパティを持っています
  • CSS の column-count プロパティがあり値が auto ではない、または CSS column-width プロパティがあり値が auto ではない
  • 現在、アニメーションは不透明度、変換、フィルター、背景フィルターに適用されています
  • オーバーフローは表示されません

24. ルーティング原理の歴史とハッシュルーティング方式の特徴

ハッシュモード

  1. location.hash の値は、実際には URL の # 以降の値であり、その特徴は、URL にはハッシュが表示されますが、HTTP リクエストには含まれず、バックエンドにはまったく影響を与えないことです。ハッシュはページをリロードしません。
  2. ハッシュ変更のリスナーイベントを追加できます

window.addEventListener(“hashchange”, funcRef, false);
ハッシュ(window.location.hash)を変更するたびに、ブラウザのアクセス履歴に記録が追加されます 上記のハッシュの性質を利用して、フロントエンドを実現できます。 -end routing "update" 表示しますがページを再リクエストしません」
機能: 互換性は良いが美しくはない

履歴モード

HTML5 履歴インターフェイスの新しい PushState() メソッドと replaceState() メソッドを活用してください。
これら 2 つのメソッドはブラウザの履歴記録ステーションに適用され、既存の戻る、進む、進むをベースに、履歴記録を変更する機能を提供します。これら 2 つのメソッドには共通の特徴があります。ブラウザ履歴スタックを変更するために呼び出された場合、現在の URL が変更されていても、ブラウザはページを更新しません。これは、シングルページ アプリケーションのフロントエンド ルートである「更新」です。ページは表示しますが、再リクエストはしないでください」が根拠となります。
特徴:綺麗ですが更新時に404が表示されバックエンドの設定が必要

25. XMLHttpRequest と fetch の違いは何ですか?

(1).XMLHttpRequest オブジェクトは、最新のすべてのブラウザでサポートされています。Fetch は、現在ほとんどのブラウザでサポートされている新しいネイティブ JavaScript API です。(2) .XMLHttpRequest は、onreadystatechange に基づいてコールバックを実行します。Fetch API は Promise を使用してコールバックを回避します

(3). Fetch はネットワーク リクエストのエラーのみを報告し、400 と 500 を成功したリクエストとして扱います。これらは処理のためにカプセル化する必要があります。
(4). フェッチ リクエストにはデフォルトでは Cookie がないため、fetch(url, {credentials: 'include'}) を設定する必要があります。
(5). Fetch は Promise を返し、タイムアウト制御をサポートしていないため、Fetch はアボートをサポートしていません。setTimeout と Promise.reject を使用して実装されたタイムアウト制御では、リクエスト プロセスがバックグラウンドで実行され続けることを防ぐことができず、無駄が発生します。量の。
(6). .fetch() の例では、文字列で定義された URL エンドポイントを渡すことも、構成可能な Request オブジェクトを渡すこともできます。
(7). XMLHttpRequest でキャッシュを管理するのは面倒です。Fetch オブジェクトにはキャッシュのサポートが組み込まれています: (8).
クロスドメイン要求では、Fetch は 'no-cors' 属性を設定できる mode 属性を提供します。パラメータで。
(9). デフォルトでは、fetch() と XMLHttpRequest は両方ともサーバー リダイレクトに従います。ただし、 fetch() はパラメータにオプションのオプションを提供します。
リダイレクト
'follow' - すべてのリダイレクトに従います (デフォルト)
'error' - リダイレクトが発生した場合に中止 (拒否)
'manual' - 手動で処理された応答を返します

(10).XMLHttpRequest は応答全体をメモリ バッファーに読み取りますが、fetch() は要求データと応答データをストリーミングできます。これは、送受信時に小さなデータ チャンクを処理できる新しいテクノロジです。
(11). フェッチは Deno と Node で完全にサポートされており、XMLHttpRequest はクライアント側でのみサポートされています。

26. フロントエンドは大きなファイルのダウンロードをどのように実装しますか?

(1). バックエンドサービスがサポートしている場合は、部分ダウンロードを使用できます。
(2). クラウド上のファイルをブラウザのデフォルトの仕組みでタグ方式でダウンロード可能
(3). StreamAPIとService Workerを利用して実現

27. いくつかの一般的なフロントエンド マイクロサービスとその実装原則

マイクロ フロントエンド アーキテクチャは、バックエンド マイクロサービスの概念をブラウザーに適用します。つまり、Web アプリケーションを単一のアプリケーションから、複数の小さなフロントエンド アプリケーションを 1 つに集約したアプリケーションに変換します。
マイクロフロントエンド アーキテクチャは通常、次の方法で実装できます。

  1. ルート配信

ルーティングを通じて、さまざまなサービスをさまざまな独立したフロントエンド アプリケーションに配信します。通常、HTTP サーバーのリバース プロキシ、またはアプリケーション フレームワークに付属するルーティングを通じて実装できます。

  1. iframeコンテナ経由

iframe を使用して新しい独立したホスト環境を作成し、独立したフロントエンド アプリケーションを実行する

  1. フロントエンドのマイクロサービス

ページ上の適切な場所に DOM を導入または作成し、ユーザーが対応する URL にアクセスすると、対応するアプリケーションが読み込まれ、アプリケーションをアンインストールできます。

  1. アプリのウィジェット化

これは複合統合とも呼ばれます。つまり、ソフトウェア エンジニアリングを通じて、アプリケーションが構築前、構築、構築後の段階で分割され、再組み立てされます。

  1. Web コンポーネントに基づく

Web コンポーネント テクノロジを使用してフレームワークに依存しないコンポーネントを構築し、これらのコンポーネントを対応するフレームワークに導入します。

28. フロントエンド展開のソリューションは何ですか?

フロントエンドの導入方法は大きく分けて3つあります。

  • Nginx、Tomcat、IIS、およびその他の Web サーバーを使用して展開します
  • Docker のデプロイメント
  • OSS+CDN 導入、または COS

29. 一般的な出版スキームがいくつかあります

  1. ブルーグリーンリリース

ブルーグリーンリリースとは、リリースプロセス中に新しいアプリケーションのリリーステストに合格した後、ゲートウェイトラフィックを切り替えてアプリケーションを更新するワンクリックリリース方法を指します。

  1. ローリングリリース

一般に、1 つ以上のサービスが停止され、更新が実行され、再び使用されるようになります。マイクロサービス内のすべてのパブリック サービスが新しいバージョンに更新されるまで、このサイクルが繰り返されます。

  1. グレーリリース

黒と白の間をスムーズに移行できる出版方法を指します。ABテストは、一部のユーザーはAを使い続け、一部のユーザーはBを使い始めるというグレースケールのリリース方法です。ユーザーがBに抵抗がない場合は、段階的に範囲を拡大し、すべてのユーザーをBに移行します。グレースケール リリースでは、システム全体の安定性を確保できます。最初のグレースケール中に問題を見つけて調整し、その影響を確実にすることができます。通常、カナリア デプロイメントと呼ばれるものも、グレースケール リリースの 1 つの方法です。

30. A/B プランの設計方法

A/B パブリッシングは、URL が一致するかどうかに基づいて異なるバージョンのアプリケーションを要求したり、ヘッダーの下のカスタム パラメーターに基づいてユーザーを区別したりするなど、比較的高度なトラフィック分散スキームです。これにより、異なるバージョンのアプリケーションの要求にはトラフィック管理戦略が関係します。
, Istio、docker、k8s などのテクノロジーにより、
マイクロサービスやクラウド ネイティブの概念が徐々に深まり、既存のフロントエンド開発手法やフロントエンド アーキテクチャも変化し続けます。上記のテクノロジーを上手に活用することで、より高速に実現できますアプリケーション間の接続がより緊密になり、今後数年間でフロントエンドもマイクロサービスの時代となるでしょう。

結論:

       これを見て、何か得したことはあるでしょうか?さらに凍結防止ガイドをお持ちの場合は、コメント欄に残して必要な友達に任せてください。上記の内容についてまだ質問がある場合は、メッセージを残して交換してください。インターネットの冬は誰もフリーズしません。準備をしてください、JY~

おすすめ

転載: blog.csdn.net/gaojinbo0531/article/details/129404773