第 100 题:请写出如下代码的打印结果
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();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(36)
421
4
2
1
这个我会,来声个张,
421~
声明顺序:
Foo.a = function() { console.log(4) }
所以第一个为4,
接下来new了一下构造函数~
虽然把原型链挂到了新obj,
但是,构造函数重定义了Foo.a,且设定构造函数的娃的a为2。
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();
`Foo.a(); // 4 全局的Foo.a
let obj = new Foo(); // 执行Foo的构造函数,将 最后的 Foo.a(全局)覆盖
obj.a(); // 2 this.a
Foo.a(); // 1 Foo构造函数里的 foo.a 因为全局的已经被覆盖
`
京东怎么总喜欢出这种乱七八糟的题
421
大家回答挺好的,考察的是原型链和实例的问题
这道题很好的讲述了构造函数中,new做的事情:
(1)创建一个新对象;
(2)将构造函数的作用域赋给新对象(因此this就指向了这个对象);所以,obj.a()输出2
(3)执行构造函数中的代码(为这个新对象添加属性); 所以Foo.a()输出1,因为被覆盖了
(4)返回新对象。
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)`
思路:
结果:4,2,1
100题达成 前面又忘了(bushi)。。。
打印顺序 4 2 1
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
答案为:4, 2, 1
解析:
Foo.a()
这个是调用 Foo 函数的静态方法 a,虽然 Foo 中有优先级更高的属性方法 a,但 Foo 此时没有被调用,所以此时输出 Foo 的静态方法 a 的结果:4let obj = new Foo();
使用了 new 方法调用了函数,返回了函数实例对象,此时 Foo 函数内部的属性方法初始化,原型方法建立。obj.a();
调用 obj 实例上的方法 a,该实例上目前有两个 a 方法:一个是内部属性方法,另一个是原型方法。当这两者重名时,前者的优先级更高,会覆盖后者,所以输出:2Foo.a();
根据第2步可知 Foo 函数内部的属性方法已初始化,覆盖了同名的静态方法,所以输出:1421
// 定义一个构造函数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();
那些只说结果不去分析的,有啥意义。。
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
4,2,1
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。
输出顺序:4,2,1
4 2 1
4 2 1
421
4
2
1
4 2 1
4 2 1
输出顺序是 4 2 1 .
结果如下