3つの問題はJavaScript関数、変数、対象、作用域に対する理解度を考察します.
4324 ワード
試し牛刀
この文章は一つの問題から始まります.後は徐々にこの問題をもとに展開します.まず下記のコードを実行してから出力されるものは何かを考えてみます.
getAge()
var getAge = function(){
console.log(18);
}
function getAge(){
console.log(20);
}
getAge()
この問題は二つの知識点を試験しました.一つはJavaScriptにおける変数の昇格です.もう一つは関数の定義は関数宣言と関数式の2種類があります.変数アップとは?
fun()
function fun(){
console.log(' ');
}
fun()
上記は関数宣言の方式であり、変数アップ機構によって、ここでのfun()が一番上に引き上げられるので、ここでの結果は明らかである./* */
fun() //
function fun(){
console.log(' ');
}
fun() //
この例を通して、関数宣言はJS解析時に関数の向上を行うので、同じスコープ内では関数がどこで宣言を定義しても、この関数は呼び出されます.関数式
fun()
var fun = function(){
console.log(' ');
}
表式宣言は、関数を変数に割り当てます.この変数はもちろん、一番前に引き上げられますが、ここにはピットがあります.変数の昇格は変数を一番前に上げただけですが、割当はJS運転時に行います.出力結果を見て,funは関数ではないことを示した.fun() //Uncaught TypeError: fun is not a function
var fun = function(){
console.log(' ');
}
funを後ろに置いてみます.var fun = function(){
console.log(' ');
}
fun() //
fun関数は正常に実行できます.この時点で既に割り当てられています.上の内容を理解してから、初めの問題を振り返ってみます.答えは次の通りです.
getAge() // 20
var getAge = function(){
console.log(18);
}
function getAge(){
console.log(20);
}
getAge() //18
関数オブジェクトJavaScriptでは関数も対象となり、自分の構造関数を持ち、プロトタイプチェーンもあります.同じ思考問題から始まります.
function Person(){
getAge = function(){
console.log(17);
}
this.getAge = function(){
console.log(18);
}
}
Person.getAge = function(){
console.log(19);
}
Person.prototype.getAge = function(){
console.log(20);
}
Person.getAge()
new Person().getAge()
この問題は主に対象の私有属性/方法、公有属性/方法、静的属性/方法を考察します.new Person().getAge() このステップは、まずPersonを実装し、インスタンスのgetAge()方法を呼び出した.本質はこのような順序(new Person()getAge()です.でも今は問題があります.Personさん. 構造関数とプロトタイプ鎖の両方にgetAge()法がある.この場合はプロトタイプではなくコンストラクタ内の公有法をデフォルトで使用します.
function Person(){
function getAge(){ //
console.log(17);
}
this.getAge = function(){ //
console.log(18);
}
}
Person.getAge = function(){ //
console.log(19);
}
Person.prototype.getAge = function(){ //
console.log(20);
}
Person.getAge() //19
new Person().getAge() //18
thisの指向この問題は前の問題に対して難しいです.ここでは主にthisと作用域に対する考察です.
function Person(){
this.getAge = function(){
console.log(18);
}
getAge = function(){
console.log(19);
}
return this
}
var getAge = function(){
console.log(20);
}
getAge()
Person().getAge()
new Person().getAge()
getAge()
第一問:getAge() ,これは比較的簡単です.説明できるものはありません.ただgetAge関数を実行します.第二の質問:Person().getAge()は最初にPerson()関数を実行し、その後Person関数から返されたオブジェクトのgetAge属性関数を呼び出します.その中のgetAge=function(){consolie.log(19)}は、現在の作用領域ではgetAgeが宣言されていないため、上位の作用領域に変数getAgeを探しています.外部ではvar getAge=function(){consolie.log(20)}変数が向上していますので、ここではグローバル変数getAgeが修正されたのに相当します.関数から返されたthisはここではwindowを指します.ここではPerson関数を実行しますが、実用化されていません.だからPerson().getAge()はwindowでのgetAgeメソッドの呼び出しに相当し、最終的な出力結果は19です.
第三の質問:第二の質問とは違って、ここでPersonを実例化したので、ここで戻ってきたthisは戻ってきた例を指し、次いでこの実例の公有方法、つまりthis.getAgeを呼び出します.
第四問:この質問は第一問とほぼ同じように見えますが、第二問の分析により、グローバル変数getAgeは第二問で修正されたので、ここの出力は19です.
コンストラクタの戻り値
従来の言語では、コンストラクタは値を返していません.実際の戻り値はこのコンストラクターのものです.
JavaScriptの中の構造関数は戻り値があってもいいし、なくてもいいです.ここでは3つの状況に分けられます.
function Person(name){
this.name = name
}
console.log(new Person('bbb').name); //bbb
function Person(name){
this.name = name
name = 'aaa'
return name
}
console.log(new Person('bbb').name); //bbb
function Person(name){
this.name = name
name = 'aaa'
return name
}
console.log(new Person('bbb').name); //bbb