StackOverflow の調査によると、JavaScript は 2014 年以来最も人気のあるプログラミング言語です。もちろん、開発作業の 1/3 には JavaScript の知識が必要なので、これは当然のことです。したがって、開発者になりたい場合は、この言語を学ぶ必要があります。
このブログの主な目的は、すべてのインタビューに共通する概念をまとめて、すぐに理解できるようにすることです。 (この記事の内容が長すぎて読みにくいため、3 つのブログに分けて翻訳します。今回は 3 番目の部分です。最初の部分は、「JavaScript 面接の基礎をすぐにマスターする」をクリックしてください ( 1))
おすすめ関連記事: 2020年最も包括的なJS面接質問集(最新)
新しいキーワード
new
を使用する場合> 関数を呼び出すためのキーワードですが、これは非常に特殊な形式です。 new
コンストラクター関数で呼び出される関数を呼び出します。 new
关键字来调用函数式很特别的形式。我们把那些用new
调用的函数叫做构造函数(constructor function)。
使用了new
的函数到底做了什么事情呢?
创建一个新的对象
将对象的prototype设置为构造函数的prototype
执行构造函数,
this
执行新构造的对象返回该对象。如果构造函数返回对象,那么返回该构造对象。
// 为了更好地理解底层,我们来定义new关键字 function myNew(constructor, ...arguments) { var obj = {} Object.setPrototypeOf(obj, constructor.prototype); return constructor.apply(obj, arguments) || obj }
使用new
和不使用的区别在哪里呢?
function Bird() { this.wings = 2; } /* 普通的函数调用 */ let fakeBird = Bird(); console.log(fakeBird); // undefined /* 使用new调用 */ let realBird= new Bird(); console.log(realBird) // { wings: 2 }
为了便于对比理解,译者额外增加了测试了一种情况:
function MBird(){ this.wings =2; return "hello"; } let realMBrid = new MBird(); console.log(realMBird) // { wings: 2 }
你会发现,这一句return "hello"
并没有生效!
原型和继承
原型(Prototype)是JavaScript中最容易搞混的概念,其中一个原因是prototype
可以用在两个不同的情形下。
原型关系
每一个对象都有一个prototype
对象,里面包含了所有它的原型的属性。.__proto__
是一个不正规的机制(ES6中提供),用来获取一个对象的prototype。你可以理解为它指向对象的parent
。
所有普通的对象都继承.constructor
属性,它指向该对象的构造函数。当一个对象通过构造函数实现的时候,__proto__
属性指向构造函数的构造函数的.prototype
。Object.getPrototypeOf()
是ES5的标准函数,用来获取一个对象的原型。原型属性
每一个函数都有一个.prototype
属性,它包含了所有可以被继承的属性。该对象默认包含了指向原构造函数的.constructor
属性。每一个使用构造函数创建的对象都有一个构造函数属性。
接下来通过例子来帮助理解:
function Dog(breed, name){ this.breed = breed, this.name = name } Dog.prototype.describe = function() { console.log(`${this.name} is a ${this.breed}`) } const rusty = new Dog('Beagle', 'Rusty'); /* .prototype 属性包含了构造函数以及构造函数中在prototype上定义的属性。*/ console.log(Dog.prototype) // { describe: ƒ , constructor: ƒ } /* 使用Dog构造函数构造的对象 */ console.log(rusty) // { breed: "Beagle", name: "Rusty" } /* 从构造函数的原型中继承下来的属性或函数 */ console.log(rusty.describe()) // "Rusty is a Beagle" /* .__proto__ 属性指向构造函数的.prototype属性 */ console.log(rusty.__proto__) // { describe: ƒ , constructor: ƒ } /* .constructor 属性指向构造函数 */ console.log(rusty.constructor) // ƒ Dog(breed, name) { ... }
JavaScript的使用可以说相当灵活,为了避免出bug了不知道,不妨接入Fundebug线上实时监控。
原型链
原型链是指对象之间通过prototype链接起来,形成一个有向的链条。当访问一个对象的某个属性的时候,JavaScript引擎会首先查看该对象是否包含该属性。如果没有,就去查找对象的prototype中是否包含。以此类推,直到找到该属性或则找到最后一个对象。最后一个对象的prototype默认为null。
拥有 vs 继承
一个对象有两种属性,分别是它自身定义的和继承的。
function Car() { } Car.prototype.wheels = 4; Car.prototype.airbags = 1; var myCar = new Car(); myCar.color = 'black'; /* 原型链中的属性也可以通过in来查看: */ console.log('airbags' in myCar) // true console.log(myCar.wheels) // 4 console.log(myCar.year) // undefined /* 通过hasOwnProperty来查看是否拥有该属性: */ console.log(myCar.hasOwnProperty('airbags')) // false — Inherited console.log(myCar.hasOwnProperty('color')) // true
Object.create(obj)
创建一个新的对象,prototype指向obj
new
を使用した関数は具体的に何をするのですか? this
は新しく構築されたオブジェクト
を実行し、オブジェクトを返します。コンストラクターがオブジェクトを返す場合、構築されたオブジェクトが返されます。
var dog = { legs: 4 }; var myDog = Object.create(dog); console.log(myDog.hasOwnProperty('legs')) // false console.log(myDog.legs) // 4 console.log(myDog.__proto__ === dog) // true
new
を使用する場合と使用しない場合の違いは何ですか?
var objProt = { text: 'original' }; var objAttachedToProt = Object.create(objProt); console.log(objAttachedToProt.text) // original // 我们更改objProt的text属性,objAttachedToProt的text属性同样更改了 objProt.text = 'prototype property changed'; console.log(objAttachedToProt.text) // prototype property changed // 但是如果我们讲一个新的对象赋值给objProt,那么objAttachedToProt的text属性不受影响 objProt = { text: 'replacing property' }; console.log(objAttachedToProt.text) // prototype property changed
比較と理解を容易にするために、翻訳者は追加のテスト状況を追加しました:
function greetingAsync(name, callback){ let greeting = "hello, " + name ; setTimeout(_ => callback(greeting),0); } greetingAsync("fundebug", console.log); console.log("start greeting");
この文 return "hello"
は有効ではないことがわかります。
プロトタイプ
が 2 つの異なる状況で使用できることです。 🎜- 🎜プロトタイプの関係🎜 すべてのオブジェクトには、そのプロトタイプのすべてのプロパティが含まれる
prototype
オブジェクトがあります。 🎜.__proto__
は、オブジェクトのプロトタイプを取得するために使用される非公式メカニズム (ES6 で提供) です。これは、オブジェクトのparent
を指していると理解できます。 🎜すべての通常のオブジェクトは、オブジェクトのコンストラクターを指す.constructor
属性を継承します。オブジェクトがコンストラクターを通じて実装される場合、__proto__
属性は、コンストラクターのコンストラクターの.prototype
を指します。Object.getPrototypeOf()
は ES5 の標準関数で、オブジェクトのプロトタイプを取得するために使用されます。 🎜 - 🎜プロトタイプ属性🎜すべての関数には
.prototype
属性があり、継承できるすべての属性が含まれています。デフォルトでは、オブジェクトには元のコンストラクターを指す.constructor
プロパティが含まれています。コンストラクターを使用して作成されたすべてのオブジェクトには、コンストラクター プロパティがあります。 🎜
const first = function () { console.log('First message') } const second = function () { console.log('Second message') } const third = function() { console.log('Third message') } first(); setTimeout(second, 0); third(); // 输出: // First message // Third message // Second message🎜JavaScript の使用は、いつバグが発生するかわからないことを避けるために、非常に柔軟であると言えます。また、Fundebug に接続して、 オンラインでリアルタイム監視することもできます。 🎜🎜プロトタイプ チェーン🎜🎜 プロトタイプ チェーンは、プロトタイプを介してリンクされ、有向チェーンを形成するオブジェクトを指します。オブジェクトのプロパティにアクセスするとき、JavaScript エンジンはまずオブジェクトにそのプロパティが含まれているかどうかを確認します。含まれていない場合は、それがオブジェクトのプロトタイプに含まれているかどうかを確認してください。プロパティが見つかるか、最後のオブジェクトが見つかるまで続きます。最後のオブジェクトのプロトタイプはデフォルトで null になります。 🎜🎜所有と継承🎜🎜 オブジェクトには、独自に定義されたプロパティと継承されたプロパティの 2 種類のプロパティがあります。 🎜rrreee🎜
Object.create(obj)
は新しいオブジェクトを作成します。プロトタイプは obj
を指します。 🎜rrreee🎜継承は参照渡しです🎜🎜継承されたプロパティはすべて参照の形式です。例を通してそれを鮮明に理解しましょう: 🎜rrreee🎜クラシック継承 vs プロトタイプ継承🎜🎜Eric Elliott の記事には非常に詳細な紹介があります: Master the JavaScript Interview: What's the Difference Between Class & Prototypal Inheritance?🎜 著者は、プロトタイプ継承の方が優れていると考えています。古典的な継承を継承し、ビデオによる紹介を提供しています: https://www.youtube.com/watch...🎜🎜非同期 JavaScript🎜🎜JavaScript はシングルスレッドのプログラミング言語です。つまり、JavaScript エンジンは特定の機能のみを実行できます。段落ごとのタイムコード。これが引き起こす問題は、コードの実行に長い時間がかかると、他の操作が停止してしまうことです。 JavaScript は呼び出しスタックを使用して関数呼び出しを記録します。呼び出しスタックは、書籍のスタックとして見ることができます。最後の本が一番上に置かれ、最初に削除されます。最初に置かれた本は一番下にあり、最後に取り除かれます。 🎜🎜複雑なコードが長時間にわたって CPU を占有することを防ぐための 1 つの解決策は、非同期コールバック関数を定義することです。非同期関数を自分で定義してみましょう: 🎜function greetingAsync(name, callback){ let greeting = "hello, " + name ; setTimeout(_ => callback(greeting),0); } greetingAsync("fundebug", console.log); console.log("start greeting");
我们在greetingAsync
中构造了greeting
语句,然后通过setTimeout
定义了异步,callback
函数,是为了让用户自己去定义greeting的具体方式。为方便起见,我们时候直接使用console.log
。
上面代码执行首先会打印start greeting
,然后才是hello, fundebug
。也就是说,greetingAsync
的回调函数后执行。在网站开发中,和服务器交互的时候需要不断地发送各种请求,而一个页面可能有几十个请求。如果我们一个一个按照顺序来请求并等待结果,串行的执行会使得网页加载很慢。通过异步的方式,我们可以先发请求,然后在回调中处理请求结果,高效低并发处理。
下面通过一个例子来描述整个执行过程:
const first = function () { console.log('First message') } const second = function () { console.log('Second message') } const third = function() { console.log('Third message') } first(); setTimeout(second, 0); third(); // 输出: // First message // Third message // Second message
初始状态下,浏览器控制台没有输出,并且事件管理器(Event Manager)是空的;
first()
被添加到调用栈将
console.log("First message")
加到调用栈console.log("First message")
执行并输出“First message”到控制台console.log("First message")
从调用栈中移除first()
从调用栈中移除setTimeout(second, 0)
加到调用栈setTimeout(second, 0)
执行,0ms之后,second()
被加到回调队列setTimeout(second, 0)
从调用栈中移除third()
加到调用栈console.log("Third message")
加到调用栈console.log("Third message")
执行并输出“Third message”到控制台console.log("Third message")
从调用栈中移除third()
从调用栈中移除Event Loop 将
second()
从回调队列移到调用栈console.log("Second message")
加到调用栈console.log("Second message")
Second message”到控制台console.log("Second message")
从调用栈中移除Second()
从调用栈中移除
特别注意的是:second()
函数在0ms之后并没有立即执行,你传入到setTimeout()
函数的时间和second()
延迟执行的时间并不一定直接相关。事件管理器等到setTimeout()
设置的时间到期才会将其加入回调队列,而回调队列中它执行的时间和它在队列中的位置已经它前面的函数的执行时间有关。
相关学习推荐:javascript视频教程
以上がJavaScript 面接の基礎知識の質問の共有の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

WebStorm Mac版
便利なJavaScript開発ツール

メモ帳++7.3.1
使いやすく無料のコードエディター

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

SublimeText3 中国語版
中国語版、とても使いやすい

VSCode Windows 64 ビットのダウンロード
Microsoft によって発売された無料で強力な IDE エディター
