一道 javascript 面试题求教

2019-06-11 15:21:10 +08:00
 noviceiOS

这里有一道面试题:

function Foo() {
       getName = function(){
           console.log("1");
       };
       return this;
   }
   Foo.getName = function() {
       console.log("2");
   };

   Foo.prototype.getName = function(){
       console.log("3");
   };

   var getName = function() {
       console.log("4");
   };
   function getName(){
       console.log("5");
   }
   Foo.getName(); // 2 
   getName(); // 4
   Foo().getName(); //1 ? 4 ? 2 ?报错   
   getName(); // ?    1
   new Foo.getName(); //  2
   new Foo().getName(); // 3
   new new Foo().getName(); // 3

求问最后三个结果是怎么出来的,谢谢各位了。

4987 次点击
所在节点    JavaScript
32 条回复
palmers
2019-06-11 18:04:26 +08:00
@wly19960911 我一直当做了匿名函数 没看见这是一个函数声明然后变为函数表达式, 所以才会出现 a =1
但是内部的执行逻辑我也没搞懂, 大意了没仔细看就当做匿名函数了 所以我复现不出来 , 我的猜测是 函数声明变为表达式的时候和全局变量冲突的处理方式不一样, 在 firefox 中 a 就是这个函数而不是 number chrome 中依然是 number chrome 也许是把这种冲突吃掉了
求大神解释一下
像这种函数声明变为表达式的执行步骤到底是什么样的
palmers
2019-06-11 18:12:26 +08:00
在 chrome 中调试: 我上面说错了 在 debugger 之前的 log chrome 并没有认为 a 是 number 最后打印出来的还是一个函数: ƒ a() {a = 2; console.log(a); debugger;}
但是 为什么断点的时候 a 是 number 1 呢? 只能是先后顺序的问题了 这时候还没有执行函数 a 我们之所以能看见 a 为 1 是因为浏览器断点调试器 把全部为 a 的变量当前的值显示出来了而已
dd31san
2019-06-11 18:30:14 +08:00
验证了下 append,输出是函数 a,全局 a 值为 1。
尝试修改函数名 a1,运行后全局 a 值变成 2,也就是在匿名函数里,给和函数同名的 a 赋值或声明失败?=)
palmers
2019-06-11 18:31:38 +08:00
我说的好像也不对, 彻底 xx 了, 我执行下面的代码
var a = 1;
(function a(f) {
console.log('...', f);
a = 2;
console.log(a);
})(function() {
console.log('');
});

//输出这样的
... ƒ () {
console.log('');
}
ƒ a(f) {
console.log('...', f);
a = 2;
console.log(a);
}

那个函数执行过又好像没有执行过 好奇怪
rabbbit
2019-06-11 18:36:53 +08:00
palmers
2019-06-11 18:39:16 +08:00
我有一个猜的解释, 第一对小括号,把函数声明变为函数表达式,所以 a 变为了
a = function a(f) {
console.log('...', f);
a = 2;
console.log(a);
};
然后第二对小括号执行这个函数,所以有上面的打印,但是这时候 a 已经是一个函数了,所以打印了 a 函数体

那在 debugger 的时候 a 是 1 我解释不了 按道理说 只有执行函数的时候才会进入函数体的 只能去研究 chrome 的断掉调试器的机制了
palmers
2019-06-11 18:42:42 +08:00
@rabbbit 谢谢 这个解释可以
wmhx
2019-06-11 18:50:40 +08:00
写这种代码的人, 能抗几刀?
c4f36e5766583218
2019-06-11 19:07:45 +08:00
1. https://blog.csdn.net/xjb19901008/article/details/24930793
hoisting 参考: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types

____1.1 function 提升

____1.2 var 定义提升( ps: 还可以考 let, var, const 区别以及它们可否重复声明,还有直接赋值和语句块作用域;再还有严格模式)

2. this 的值
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

3. prototype
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes

4. 运算符优先级
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence

所以可以理解为:
```JavaScript
// part1 function
function Foo() {
getName = function() {
console.log("1");
}
return this;
}
function getName() {
console.log("5");
}
// part2 var
var getName;
// part3
Foo.getName = function() {
console.log("2");
}
Foo.prototype.getName = function() {
console.log("3");
}
getName = function() {
console.log("4");
};
// part4
Foo.getName(); // 2
getName(); // 4
Foo().getName(); // 1,直接赋值是全局变量,这里 Foo()执行后返回的是 Window
getName(); // 1,被上一句的 Foo()修改了
new Foo.getName(); // 2,new (Foo.getName)()
new Foo().getName(); // 3,(new Foo()).getName()
new new Foo().getName(); // 3,先 new 再.再 new
```

第二题就是直接赋值和 https://developer.mozilla.org/en-US/docs/Glossary/IIFE
c4f36e5766583218
2019-06-11 19:11:20 +08:00
@c4f36e5766583218 #29 哦,第二题,没看清,你当我没说。
wszgrcy
2019-06-11 19:46:41 +08:00
又看到这道为了考人而考人的提。。。主就是原型链和运算符顺序已经某些不规范的隐藏写法。。。。
AddOneG
2019-06-11 22:57:23 +08:00
题 1 没啥好讲的。
题 2:非匿名自执行函数,函数变量为 只读 状态,无法修改。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/572816

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX