出典:フルスタックのフロントエンドの選択
読みやすくするために、各エラーは短縮されています。これらの問題の原因と回避方法を特定するために、各問題をさらに詳しく調べてみましょう。
1. Uncaught TypeError:プロパティを読み取れません
JavaScript開発者であれば、このエラーが発生している可能性があります。これは、プロパティを読み取るか、未定義のオブジェクトのメソッドを呼び出すと、Chromeで発生します。Chromeデベロッパーコンソールで簡単にテストできます。
これには多くの理由がありますが、一般的な理由は、UIコンポーネントをレンダリングするときの不適切な状態初期化です。これが実際のアプリケーションでどのように行われるかの例を見てみましょう。Reactを選択しますが、不正な初期化と同じ原則がAngular、Vue、またはその他のフレームワークにも適用されます。
class Quiz extends Component {
componentWillMount() {
axios.get('/thedata').then(res => {
this.setState({items: res.data});
});
}
render() {
return (
<ul>
{this.state.items.map(item =>
<li key={item.id}>{item.name}</li>
)}
</ul>
);
}
}
ここで注意すべき重要なことが2つあります。
コンポーネントの状態(など
this.state
)undefined
は、状態の使用を開始します。データを非同期で取得する場合、データがコンストラクターで取得された
componentWillMount
か 、コンストラクターで取得されたかに関係なくcomponentDidMount
、データがロードされる前にコンポーネントが少なくとも1回レンダリングされます。クイズを初めてレンダリングしたときは、this.state.items
はいundefined
。これは、ItemListが未定義の項目を取得し、コンソールでエラーが発生することを意味します-"UncaughtTypeError:未定義のプロパティ 'map'を読み取れません"。
これは簡単に解決でき、最も簡単な方法:コンストラクターで適切なデフォルト値で状態を初期化します。
class Quiz extends Component {
// 添加了这个:
constructor(props) {
super(props);
this.state = {
items: [] // 默认值
};
}
componentWillMount() {
axios.get('/thedata').then(res => {
this.setState({items: res.data});
});
}
render() {
return (
<ul>
{this.state.items.map(item =>
<li key={item.id}>{item.name}</li>
)}
</ul>
);
}
}
アプリケーションの実際のコードは異なる場合がありますが、アプリケーションでこの問題を修正または回避するための十分な手掛かりが得られたと思います。そうでない場合は、以下を読んでください。関連するエラーの例を以下に紹介します。
2. TypeError: 'undefined'はオブジェクトではありません(評価中
これはundefined
、Safariでオブジェクトのプロパティを読み取ったり、メソッドを呼び出したりするときに発生するエラーで、Safari開発者コンソールで簡単にテストできます。これは基本的に上記のChromeのエラーと同じですが、Safariは異なるエラーメッセージを使用します。
3. TypeError:nullはオブジェクトではありません(評価中
これはnull
、Safariでオブジェクトのプロパティを読み取ったり、メソッドを呼び出したりするときに発生するエラーで、Safari開発者コンソールで簡単にテストできます。
興味深いことに、JavaScriptではnullとundefinedは同じではないため、2つの異なるエラーメッセージが表示されます。Undefinedは通常、まだ割り当てられていない変数であり、nullは値が空白であることを意味します。 それらが等しいことを確認するには、厳密な等価演算子を使用してみてください。
実際の例でこのエラーが発生する可能性がある1つの方法は、要素をロードする前にJavaScriptでDOM要素を使用しようとすることです。これは、DOM APIが空のオブジェクト参照に対してnullを返すためです。
DOM要素を実行および処理するJSコードは、DOM要素の作成後に実行する必要があります。JSコードはHTML形式に従って上から下に解釈されるため、DOM要素の前にタグがある場合、ブラウザがHTMLページを解析するときにスクリプトタグのJSコードが実行されます。このエラーは、スクリプトが読み込まれる前にDOM要素が作成されていない場合に発生します。
この例では、ページの準備ができたときに通知するイベントリスナーを追加することで問題を解決できます。トリガーされる addEventListener
と、init()
メソッドはDOM要素を使用できます。
<script>
function init() {
var myButton = document.getElementById("myButton");
var myTextfield = document.getElementById("myTextfield");
myButton.onclick = function() {
var userName = myTextfield.value;
}
}
document.addEventListener('readystatechange', function() {
if (document.readyState === "complete") {
init();
}
});
</script>
<form>
<input type="text" id="myTextfield" placeholder="Type your name" />
<input type="button" id="myButton" value="Go" />
</form>
4.(不明):スクリプトエラー
発生元のポリシーに違反して、キャッチされていないJavaScriptエラーがドメインの境界を越えると、スクリプトエラーが発生します。たとえば、JavaScriptコードをCDNでホストする場合、キャッチされていないエラー(try-catchでキャッチされたエラーではなく、window.onerrorハンドラーにバブルするエラー)は「有用な情報を含める代わりに、「スクリプトエラー」。これは、ドメイン間でのデータの転送を防ぐために設計されたブラウザーのセキュリティ対策です。そうしないと、ドメインが通信できなくなります。
実際のエラーメッセージを取得するには、次の操作を行います。
Access-Control-Allow-Originヘッダーを送信する
Access-Control-Allow-Origin
ヘッダーを設定して、 *
任意のドメインからリソースに正しくアクセスできることを 示します。*
ドメインの交換が必要になる場合があり ます(例:)Access-Control-Allow-Origin:www.example.com
。ただし、複数のドメインを処理する方が複雑であり、CDNを使用する場合、キャッシュの問題が発生する可能性があり、その価値はありません。
以下は、さまざまな環境でこのヘッダーを設定する方法の例です。
Apache
JavaScriptファイルが提供されるフォルダーに、次の内容の.htaccess
ファイルを作成し ます。
Header add Access-Control-Allow-Origin "*"
Nginx
JavaScriptファイルを提供するロケーションブロックにadd_header命令を追加します。
location ~ ^/assets/ {
add_header Access-Control-Allow-Origin *;
}
HAProxy
JavaScriptファイルを提供するアセットバックエンドに以下を追加します。
rspadd Access-Control-Allow-Origin:\ *
スクリプトタグにcrossorigin = "anonymous"を設定します
HTMLソースコードで、Access-Control-Allow-Origin
ヘッダーを設定するスクリプトごとに、スクリプトタグに設定し crossorigin="anonymous"
ます。スクリプトタグにcrossorigin
属性を追加する前 に、スクリプトファイルのヘッダーが送信されていることを確認してください。Firefoxでは、 crossorigin
属性はあるがAccess-Control-Allow-Origin
ヘッダーがない 場合、スクリプトは実行されません。
5. TypeError:オブジェクトはプロパティをサポートしていません
これはIEで発生するエラーです。未定義のメソッドを呼び出すと、IE開発者コンソールでテストできます。
これは、Chromeのエラー「TypeError: 'undefined' is not a function」に相当します。はい、同じ論理エラーの場合、ブラウザによってエラーメッセージが異なる場合があります。
これは、JavaScript名前空間を使用するWebアプリケーションにおけるIEの一般的な問題であり、この場合の99.9%の問題は、IEが現在の名前空間のメソッドをthis
キーワードにバインドできないこと です。
たとえば、JS名前空間 Rollbar
がisAwesome
メソッドを使用 する場合。一般に、 Rollbar
名前空間にいる場合は、次の構文を使用してisAwesome
メソッドを呼び出すことができます 。
this.isAwesome();
Chrome、Firefox、Operaはこの構文を受け入れます。一方、IEはしません。したがって、JS名前空間を使用する場合、最も安全な方法は、実際の名前空間を接頭辞として使用することです。
Rollbar.isAwesome();
6. TypeError: 'undefined'は関数ではありません
これは、未定義の関数を呼び出すときにChromeで発生するエラーです。これは、ChromeデベロッパーコンソールとMozilla Firefoxデベロッパーコンソールでテストできます。
JavaScriptのコーディング手法とデザインパターンが年々複雑になってきているため、コールバックとクロージャでの自己参照の範囲もそれに応じて増加しており、これもある種の混乱のかなり一般的な原因です。
次のサンプルコードスニペットを考えてみます。
function clearBoard(){
alert("Cleared");
}
document.addEventListener("click", function(){
this.clearBoard(); // 这个 "this" 是什么?
});
上記のコードを実行してページをクリックすると、「Uncaught TypeError:this.clearBoard not a function」というエラーが発生します。その理由は、匿名関数は、ドキュメントのコンテキスト内で実行されることである clearBoard
れている window
定義します。
古いブラウザーと互換性のある従来の解決策は、変数への参照を単に保存することであり、クロージャーはこの変数を継承できます。例えば:
var self = this;
document.addEventListener("click", function(){
self.clearBoard();
});
さらに、新しいブラウザでは、bind()
メソッドを使用して正しい参照を渡すことができます 。
document.addEventListener("click",this.clearBoard.bind(this));
7. Uncaught RangeError:最大コールスタック
これは、いくつかの状況でChromeブラウザーで発生するエラーです。1つは、終了しない再帰関数を呼び出すことです。これはChromeデベロッパーコンソールでテストできます。
これは、範囲外の関数に値を渡した場合にも発生する可能性があります。多くの機能は、例えば、入力値の特定の範囲内の数値を受け入れ、Number.toExponential(digits)
そして Number.toFixed(digits)
0と20の間の数値を受け入れ、Number.toFixed(digits)
1と21の間の数字を受け入れます。
var a = newArray(4294967295); //OK
var b = newArray(-1); //range error
var num = 2.555555;
document.writeln(num.toExponential(4)); //OK
document.writeln(num.toExponential(-2)); //range error!
num = 2.9999;
document.writeln(num.toFixed(2)); //OK
document.writeln(num.toFixed(25)); //range error!
num = 2.3456;
document.writeln(num.toPrecision(1)); //OK
document.writeln(num.toPrecision(22)); //range error!
8. TypeError:プロパティ 'length'を読み取れません
これは、未定義の変数の長さプロパティが読み取られ、Chromeデベロッパーコンソールでテストできるため、Chromeブラウザで発生するエラーです。
通常、配列で定義された長さを見つけることができますが、配列が初期化されていないか、変数名が他のコンテキストで非表示になっている場合、このエラーが発生する可能性があります。次の例でこのエラーを理解しましょう。
var testArray= ["Test"];
function testFunction(testArray) {
for (var i = 0; i < testArray.length; i++) {
console.log(testArray[i]);
}
}
testFunction();
パラメータ付きの関数を宣言すると、これらのパラメータはローカルパラメータになります。つまりtestArray
、変数に名前を付けていても 、関数内の同じ名前のパラメーターはローカルパラメーターとして扱われます。
次の2つの方法で問題を解決できます。
関数宣言ステートメントのパラメーターを削除します(関数の外部で宣言された変数にアクセスする必要があるため、関数のパラメーターを使用する必要がないことがわかります)。
var testArray = ["Test"];
/* 前置条件:在函数外部定义testArray */
function testFunction(/* No params */) {
for (var i = 0; i < testArray.length; i++) {
console.log(testArray[i]);
}
}
testFunction()
関数を呼び出し、宣言した配列をそれに渡します。
var testArray = ["Test"];
function testFunction(testArray) {
for (var i = 0; i < testArray.length; i++) {
console.log(testArray[i]);
}
}
testFunction(testArray);
9. Uncaught TypeError:プロパティを設定できません
未定義の変数にアクセスしようとすると、常に戻り undefined
、undefined
プロパティを取得または設定できません 。この場合、アプリケーションは "Uncaught TypeError:プロパティを設定できません"を発生させます。
たとえば、Chromeブラウザでは次のようになります。
場合は test
、オブジェクトが存在しない場合、エラーが「捕捉されない例外TypeErrorを:プロパティを設定できません」発生します。
10. ReferenceError:イベントが定義されていません
undefined
このエラーは、現在のスコープ外の変数にアクセスしようとすると発生します。Chromeブラウザで非常に簡単にテストできます。
イベント処理システムを使用しているときにこのエラーを受け取った場合は、渡されたイベントオブジェクトをパラメーターとして使用していることを確認してください。IEなどの古いブラウザーはグローバル変数イベントを提供しますが、Chromeはイベント変数をハンドラーに自動的にアタッチします。Firefoxは自動的に追加しません。jQueryなどのライブラリはこの動作を標準化しようとしますが、イベントハンドラー関数に渡されたメソッドを使用することをお勧めします。
document.addEventListener("mousemove", function (event) {
console.log(event);
})
総括する
それらの多くはnullまたは未定義のエラーであることがわかります。厳密なコンパイラオプションを使用する場合は、Typescriptなどの静的型チェックシステムを使用すると、それらの使用を回避できます。型が予期されているがまだ定義されていない場合に警告することができます
交換留学
パブリックアカウント[フロントエンドユニバース]をフォローして、毎日良い記事の推奨事項を入手してください
WeChatを追加し、グループに参加してコミュニケーションする
「監視と転送」が最大のサポート