Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 100 题:请写出如下代码的打印结果 #155

Open
yygmind opened this issue Jul 7, 2019 · 36 comments
Open

第 100 题:请写出如下代码的打印结果 #155

yygmind opened this issue Jul 7, 2019 · 36 comments
Labels

Comments

@yygmind
Copy link
Contributor

yygmind commented Jul 7, 2019

function Foo() {
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
Foo.prototype.a = function() {
    console.log(3)
}
Foo.a = function() {
    console.log(4)
}
Foo.a();
let obj = new Foo();
obj.a();
Foo.a();
@huiliangShen
Copy link

结果如下

4
2
1

@noctiomg
Copy link

noctiomg commented Jul 8, 2019

输出顺序是 4 2 1 .

function Foo() {
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
// 以上只是 Foo 的构建方法,没有产生实例,此刻也没有执行

Foo.prototype.a = function() {
    console.log(3)
}
// 现在在 Foo 上挂载了原型方法 a ,方法输出值为 3

Foo.a = function() {
    console.log(4)
}
// 现在在 Foo 上挂载了直接方法 a ,输出值为 4

Foo.a();
// 立刻执行了 Foo 上的 a 方法,也就是刚刚定义的,所以
// # 输出 4

let obj = new Foo();
/* 这里调用了 Foo 的构建方法。Foo 的构建方法主要做了两件事:
1. 将全局的 Foo 上的直接方法 a 替换为一个输出 1 的方法。
2. 在新对象上挂载直接方法 a ,输出值为 2。
*/

obj.a();
// 因为有直接方法 a ,不需要去访问原型链,所以使用的是构建方法里所定义的 this.a,
// # 输出 2

Foo.a();
// 构建方法里已经替换了全局 Foo 上的 a 方法,所以
// # 输出 1

@mcDullLi
Copy link

mcDullLi commented Jul 8, 2019

4 2 1

1 similar comment
@mandyshen97
Copy link

4 2 1

@superermiao
Copy link

4
2
1

@Rainy934
Copy link

Rainy934 commented Jul 8, 2019

421

  • 考察的应该是原型和函数的理解

@taosin
Copy link

taosin commented Jul 8, 2019

4 2 1

1 similar comment
@webXLing
Copy link

webXLing commented Jul 8, 2019

4 2 1

@FISHzzj
Copy link

FISHzzj commented Jul 8, 2019

输出顺序:4,2,1

@dorseysen
Copy link

dorseysen commented Jul 8, 2019

function Foo() {
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
Foo.prototype.a = function() {
    console.log(3)
}
Foo.a = function() {
    console.log(4)
}
Foo.a();
let obj = new Foo();
obj.a();
Foo.a();

答案:

4、2、1

  Foo.a() 第一个为4没有什么异议
  new 的时候会将函数的主函数执行一遍,并将原型挂载至新的函数上,此时obj有本身来自Foo的this.a,也有原型上的prototype.a,查找obj.a时,在函数本域上有this.a,则直接输出来自于Foo的this.a,也就是console.log(2)。接下来的Foo.a,这时候Foo函数内部由于同样有Foo.a = function ...,new的时候Foo.a的值相当于被重置了,则输出1。

@TNTrocket
Copy link

4,2,1

@liangchaofei
Copy link

4,2,1

@james9527
Copy link

james9527 commented Jul 9, 2019

function Foo() {
    Foo.a = function() {
      console.log(1)
    }
    this.a = function() {
      console.log(2)
    }
}
// 实例方法
Foo.prototype.a = function() {
   console.log(3)
}
// 静态方法
Foo.a = function() {
   console.log(4)
}
Foo.a(); // 4  直接调Foo静态方法a
let obj = new Foo();
obj.a(); // 2  因是obj调用,故优先调用构造函数Foo自身的方法a,如果自身没有则执行原型链上的方法a
Foo.a(); // 1  因执行了一次new 操作,故再次调用Foo.a()时调用了Foo函数体内的静态方法a

@rongda
Copy link

rongda commented Jul 9, 2019

function Foo() { // 构造函数Foo
  Foo.a = function() {
    console.log(1)
  }
  this.a = function() {
    console.log(2)
  }
}
Foo.prototype.a = function() { // 原型上也有个a属性
  console.log(3)
}
Foo.a = function() { // 未new时,给函数对象添加a方法
  console.log(4)
}
Foo.a();  // 很自然这里打印的是 4 
let obj = new Foo(); // 实例化一个obj对象 ,执行了一次Foo函数
// 原型链
obj.__proto__ === Foo.prototype
Foo.prototype.__proto__ === Object.prototype
Object.prototype === null
obj.a(); // 2
Foo.a(); // 1

@Weathers0086
Copy link

function Foo() {
Foo.a = function() {
console.log(1)
}
this.a = function() {
console.log(2)
}
}
Foo.prototype.a = function() {
console.log(3)
}
Foo.a = function() {
console.log(4)
}
Foo.a(); //4
let obj = new Foo(); //
obj.a(); //2
Foo.a(); //1

@Saitmob
Copy link

Saitmob commented Jul 9, 2019

那些只说结果不去分析的,有啥意义。。

@Dandelion86
Copy link

// 定义一个构造函数Foo
function Foo() {
Foo.a = function() {
console.log(1)
}
this.a = function() {
console.log(2)
}
}
// 给构造函数Foo的原型对象上添加属性a
Foo.prototype.a = function() {
console.log(3)
}
// 函数也是对象,给Foo函数添加属性a
Foo.a = function() {
console.log(4)
}
// 访问Foo函数上的属性a执行 ,输出 4
Foo.a();
// 实例化出对象obj,在new的过程中,给Foo上的a重新赋值,实例化出的obj对象也有一个a
let obj = new Foo();
// 输出 2
obj.a();
// 输出1
Foo.a();

@wingmeng
Copy link

答案为:4, 2, 1
解析:

  1. Foo.a() 这个是调用 Foo 函数的静态方法 a,虽然 Foo 中有优先级更高的属性方法 a,但 Foo 此时没有被调用,所以此时输出 Foo 的静态方法 a 的结果:4
  2. let obj = new Foo(); 使用了 new 方法调用了函数,返回了函数实例对象,此时 Foo 函数内部的属性方法初始化,原型方法建立。
  3. obj.a(); 调用 obj 实例上的方法 a,该实例上目前有两个 a 方法:一个是内部属性方法,另一个是原型方法。当这两者重名时,前者的优先级更高,会覆盖后者,所以输出:2
  4. Foo.a(); 根据第2步可知 Foo 函数内部的属性方法已初始化,覆盖了同名的静态方法,所以输出:1

@Renser804
Copy link

421

1 similar comment
@abshawn
Copy link

abshawn commented Jul 10, 2019

421

@NaturelLee
Copy link

NaturelLee commented Jul 12, 2019

// 构造函数Foo
function Foo() {
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
// 在构造函数Foo的原型上添加a方法
Foo.prototype.a = function() {
    console.log(3)
}
// 在构造函数Foo上添加a方法
Foo.a = function() {
    console.log(4)
}
// 直接调用Foo.a()方法
Foo.a();
// 实例化, 会执行构造函数
// 实例化所在事情:在Foo上添加a方法,在新建实例上添加a方法,在Foo的原型上添加a方法
let obj = new Foo();
//执行Foo的实例obj的方法a
obj.a();
// 执行Foo的方法a
Foo.a();

@MissNanLan
Copy link

function Foo() {
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
Foo.prototype.a = function() {
    console.log(3)
}
Foo.a = function() {
    console.log(4)
}
Foo.a(); // 调用构造函数的自身的方法 ,所以结果是4
let obj = new Foo(); // new重新创建一个obj,使它指向Foo,拥有了构造函数的属性和方法
obj.a();  //  因为构造函数有直接方法,所以输出2
Foo.a();  // 构造函数重新全局a方法,所以结果结果是1,之前是4

// 结果是4、2、1

@dizangwang
Copy link

// 构造函数Foo
function Foo() {
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
// 在构造函数Foo的原型上添加a方法
Foo.prototype.a = function() {
    console.log(3)
}
// 在构造函数Foo上添加a方法
Foo.a = function() {
    console.log(4)
}
// 直接调用Foo.a()方法
Foo.a();
// 实例化, 会执行构造函数
// 实例化所在事情:在Foo上添加a方法,在新建实例上添加a方法,在Foo的原型上添加a方法
let obj = new Foo();
//执行Foo的实例obj的方法a
obj.a();
// 执行Foo的方法a  (Foo经过上一步实例化之后,重新绑定了a方法)
Foo.a();

@Yxiuchao
Copy link

4
2
1

@kukudeshiyi
Copy link

这个我会,来声个张,

@IAMSBLOL
Copy link

421~
声明顺序:
Foo.a = function() { console.log(4) }
所以第一个为4,

接下来new了一下构造函数~
虽然把原型链挂到了新obj,
但是,构造函数重定义了Foo.a,且设定构造函数的娃的a为2。

@kunogi
Copy link

kunogi commented Jul 21, 2019

2楼的解完美
补一句,
function Foo() { Foo.a = function() { console.log(1) } //this.a = function() {//干掉这里 让prototype上a,console出3可以生效的方法 //console.log(2) //} } Foo.prototype.a = function() { console.log(3) } Foo.a = function() { console.log(4) } Foo.a(); let obj = new Foo(); obj.a(); Foo.a();

@MissJingRongLi
Copy link

`Foo.a(); // 4 全局的Foo.a

let obj = new Foo(); // 执行Foo的构造函数,将 最后的 Foo.a(全局)覆盖

obj.a(); // 2 this.a

Foo.a(); // 1 Foo构造函数里的 foo.a 因为全局的已经被覆盖
`

@skychenbo
Copy link

京东怎么总喜欢出这种乱七八糟的题

@awesomezao
Copy link

421
大家回答挺好的,考察的是原型链和实例的问题

 function Foo() {
   Foo.a = function() {
     console.log(1);
   };
   this.a = function() {
     console.log(2);
   };
}
 
// 原型方法,在生成实例时使用
 Foo.prototype.a = function() {
   console.log(3);
};
 
// 静态方法,可以直接调用
 Foo.a = function() {
   console.log(4);
};
 
 Foo.a(); // 实例没有生成,直接调用静态方法,输出4
 let obj = new Foo();
 obj.a(); // 实例中有a,不去原型链中查找,之前在Foo.prototype.a的函数也被覆盖,输出2
 Foo.a(); // 生成实例后,Foo原型链中的静态方法被覆盖,输出1

@heightzhang
Copy link

heightzhang commented Mar 26, 2020

这道题很好的讲述了构造函数中,new做的事情:
(1)创建一个新对象;
(2)将构造函数的作用域赋给新对象(因此this就指向了这个对象);所以,obj.a()输出2
(3)执行构造函数中的代码(为这个新对象添加属性); 所以Foo.a()输出1,因为被覆盖了
(4)返回新对象。

@lunhui1994
Copy link

lunhui1994 commented May 3, 2020

function Foo() { Foo.a = function() { console.log(1) } this.a = function() { console.log(2) } }
该步骤是函数声明,函数声明会被编译器优先进行提升,并且在全局(此题为全局)词法作用域中声明了叫Foo的标识符。

Foo.prototype.a = function() { console.log(3) }
在函数原型上添加了一个a函数
Foo.a = function() { console.log(4) }

在Foo上添加了一个a函数,js中万物皆函数,所以就相当于在Foo这个对象上添加了一个新的属性a,并赋值为一个函数。要注意的是,这并不会对Foo构造(new)出来的对象造成影响。

Foo.a() 执行了上面定义的函数 console.log(4)

let obj = new Foo();

new 相当于创建一个新对象,用Foo对其进行构造,题目中Foo中对obj有影响的只有this.a = ...

obj的__proto__也会指向其构造函数Foo的原型Foo.prototype

所以当obj中查找的属性不存在时,顺着__proto__到Foo.prototype中去找,还找不到就去Object.prototype中找。

同样Foo(),说明Foo被执行了一次。
在Foo中
”Foo.a = function() {
console.log(1)
}“
这段代码首先会在Foo的作用域中寻找是否存在Foo这个标识符,若存在,会将其属性a定义。若不存在,会查找父作用域中是否存在。所以Foo.其实改的是父作用域的Foo,因为函数内部不存在这个值的。
所以这段代码,在本题目中,其实写在哪都一样。

obj.a();

由于obj自身拥有a,所以会执行console.log(2)
Foo.a();

再此执行全局作用域中的Foo.a 因为Foo()执行了对Foo.a的修改,所以console.log(1)`

@arixse
Copy link

arixse commented May 4, 2020

思路:

function Foo() {
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
Foo.prototype.a = function() {
    console.log(3)
}
Foo.a = function() {
    console.log(4)
}
Foo.a();   //由于Foo未初始化,所有不会执行构造函数中代码,所有调用的是外面的Foo.a,输出4
let obj = new Foo();   // 执行构造函数,`this.a`被执行
obj.a(); // 由于在Foo构造函数中存在`this.a`,所以此时不会向上查找原型链上的a函数,执行`this.a`中代码
Foo.a();  // 构造函数被执行,Foo.a被新的代码覆盖,此时Foo.a为构造函数内部的赋值,输出1

结果:4,2,1

@chillerxx
Copy link

100题达成 前面又忘了(bushi)。。。

@xlb233
Copy link

xlb233 commented Mar 9, 2021

打印顺序 4 2 1

function Foo() {

    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
// 给Foo类的实例的原型增加名为a的属性,打印3
Foo.prototype.a = function() {
    console.log(3)
}
// 给Foo对象增加一个名为a的属性,打印4
Foo.a = function() {
    console.log(4)
}
// 调用Foo对象的a方法,输出4
Foo.a();
// 实例化Foo类为obj对象,此时Foo构造函数被调用
// Foo对象的a属性被替换为打印1的函数
// 实例方法a被赋值为一个打印2的函数
let obj = new Foo();
obj.a(); // 2
Foo.a(); //1

@752337625
Copy link

function Foo() {
Foo.a = function() {
console.log(1)
} //静态方法
this.a = function() {
console.log(2)
}
}
Foo.prototype.a = function() {
console.log(3)
}
以上函数里面的方法,属性,原型链上的方法,属性只有实例对象才可以访问到
Foo.a = function() {
console.log(4)
}//静态方法
Foo.a(); //直接访问静态方法
let obj = new Foo(); //创建实例对象,这时候对象可以访问 原型链上的属性和方法,以及构造函数的属性和方法
obj.a(); //访问规则:先查好构造函数中是否有,没有在查看原型链中是否有
Foo.a(); //执行构造函数的时修改了静态方法
最总:4 2 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests