猛然间发现都须要在牛客网上视频面试了。html
好气人呀,一周内面试笔者竟然再原型链问题上被连续绊倒两次,而后被断定为 JS 基础薄弱。真的好气人呀,因此笔者研究了一下午的原型链,打算以后不再会被这个绊倒,其遇到的题目和你们分享。面试
Function.prototype.a = () => { console.log(1); } Object.prototype.b = () => { console.log(2); } function A() {} const a = new A(); a.a(); a.b(); A.a(); A.b();
真的再不少地方出现了,我一搜才发现其余朋友在 JD 的面试上也遇到过。我遇到的当晚也写了一份解答思路:面试:Function.prototype.a 请给出下列函数的执行输出算法
对于 new 出来的对象 a 的属性,原型链查找的顺序应该是promise
1. a 自身 2. `a.__proto__` 至关于 A.prototype 3. `A.prototype.__proto__` 至关于 Object.prototype 4. `Object.prototype.__proto__` 这个为 null,原型链查找到头。
对于 function 定义的函数 A 的属性,原型链查找顺序应该是闭包
1. A 自身 2. `A.__proto__` 至关于 Function.prototype 3. `Function.prototype.__proto__` 等于 Object.prototype 4. `Object.prototype.__proto__` 这个为 null,原型链查找到头。
function A() { } A.prototype.n = 0; A.prototype.add = function () { this.n += 1; } a = new A(); b = new A(); a.add(); console.log(b.add())
这是在快手后的网易面试,自从有了题1,我对这一套就开始疑神疑鬼的,想的复杂了。框架
构造函数 new 出来的对象,其方法 this 都指向他的实例。因此调用完 add 方法,遇到 this.n += 1;
,这个 this 指向的又是实例对象。因此咱们的 a 对象 和 b 对象都有独属于本身的 n。函数
function Person(name, age) { this.name = name; this.age = age; this.eat = function() { console.log(age + "岁的" + name + "在吃饭。"); } } Person.run = function () {} Person.prototype.walk = function () {} let p1 = new Person("jsliang", 24); let p2 = new Person("jsliang", 24); console.log(p1.eat === p2.eat); // false console.log(p1.run === p2.run); // true console.log(p1.walk === p2.walk); // true
new 操做符使得构造函数内的 eat 函数(对象),是在堆中新开一份空间放置,因此两个实例对象它天然不共享。this
而原型上两个实例对象天然都是同一份,walk 方法相同。prototype
须要注意的是 p1.run 和 p2.run 都是 undefined。由于 run 方法只是做为 Person 本身的静态属性,p1 和以后的原型链上是找不到的。3d
function A() { this.test = 1 } var a = new A(); a.test a = new A; a.test a = A() a.test A.test
提示读者们,的是 new A 等价与 new A(),MDN上这么说
使用指定的参数调用构造函数 Foo,并将 this 绑定到新建立的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的状况。
而 a = A()
只是把 A 做为普通函数执行了,这个普通函数内部并没有 return 出什么来,因此 a 只是 undefined,a.test 就会报错。
至于 A.test
, A 只是个函数定义,A 自己没获得执行,天然不会有什么 test 属性,只能往 Function.prototype 上找,天然仍是找不到了。
要是 Java 后三个都得报语法错误,我开始没那么喜欢 JS 了。
function A() {} function B(a) { this.a = a; } function C(a) { if (a) { this.a = a; } } A.prototype.a = 1; B.prototype.a = 1; C.prototype.a = 1; console.log(new A().a); // 1 console.log(new B().a); // undefined console.log(new C(2).a); // 2
console.log(new B().a); // undefined
,你须要知道此时 B 它自身属性里已经有了一个 a 属性了
问 foo1 上究竟都挂着什么属性
function foo() { this.some = '222' let ccc = 'ccc' foo.obkoro1 = 'obkoro1' foo.prototype.a = 'aaa' } foo.koro = '扣肉' foo.prototype.test = 'test' let foo1 = new foo() foo.prototype.test = 'test2'
foo1 上挂着属性 some,其原型链上挂着 test 和 a,至于 foo.obkoro1 只是静态属性不影响 foo1,ccc 更是闭包里的变量更不要紧。
__proto__
非标准,有什么能替代它获取原型链?去年开始出门面试,那时候被卡的是框架源码和实现细节;以后就被问各类基建系统的实现;等年初出门面几家,发现全都作算法题了;等我花了一阵子把什么链表堆栈的 leetcode 题刷过,发现最近面的没有一个问算法题,却都在问这种 “JS 基础题”。面试真的是一门玄学,怎么准备都不够。
哦,对了,还有 promise 微任务组合起来的输出的问题,也坑了我好屡次,留给后面的篇幅吧。真的好讨厌这样的问题啊!