想知道自己Js原型与原型链掌握的怎么样?来做个题试试吧!
Js原型与原型链图示:
问题集锦:
问题1:
var A = function() {};
A.prototype.n = 1;
var b = new A();
A.prototype = {
n: 2,
m: 3
}
var c = new A();
console.log(b.n);
console.log(b.m);
console.log(c.n);
console.log(c.m);
答案1:
b.n -> 1
b.m -> undefined;
c.n -> 2;
c.m -> 3;
问题2:
var F = function() {};
Object.prototype.a = function() {
console.log('a');
};
Function.prototype.b = function() {
console.log('b');
}
var f = new F();
f.a();
f.b();
F.a();
F.b();
答案2:
f.a() -> a
f.b() -> f.b is not a function
F.a() -> a
F.b() -> b
问题3:
function Person(name) {
this.name = name
}
let p = new Person('Tom');
问题1: p.__proto__
等于什么?
问题2:Person.__proto__
等于什么?
答案3:
答案1:Person.prototype
答案2:Function.prototype
问题4:
var foo = {},
F = function(){};
Object.prototype.a = 'value a';
Function.prototype.b = 'value b';
console.log(foo.a);
console.log(foo.b);
console.log(F.a);
console.log(F.b);
答案4:
foo.a => value a
foo.b => undefined
F.a => value a
F.b => value b
问题5:
function Fn() {
var num = 500;
this.x = 100;
}
Fn.prototype.getX = function () {
console.log(this.x);
}
Fn.aaa = 1000;
var f = new Fn;
console.log(f.num)
console.log(f.aaa)
var res = Fn();
console.log(res)
答案5:
f.num => undefined
f.aaa => undefined
var res = Fn(); // res是undefined Fn中的this是window
问题6:一个灵魂面试题
function Person(name) {
this.name = name
}
var p2 = new Person('king');
// 核心点:__proto__是求原型对象的,也就是求构造器的prototype属性
// ===>原型对象是构造器的一个属性,本身是个对象
//constructor 是求构造器的 ====> 构造器的prototype属性的对象集合里也有constructor,
//这个prototype里的constructor指向构造器自己
console.log(p2.__proto__)//Person.prototype
console.log(p2.__proto__.__proto__)
//结合上题,也就是Person.prototype的__proto__,Person.prototype本身是个对象,
//所以这里输出:Object.prototype
console.log(p2.__proto__.__proto__.__proto__)
//同理,这里是求Object.prototype的__proto__,这里输出:null
console.log(p2.__proto__.__proto__.__proto__.__proto__)
//null后面没有了,报错
console.log(p2.__proto__.__proto__.__proto__.__proto__.__proto__)
//null后面没有了,报错
console.log(p2.constructor)//Person
console.log(p2.prototype)
//undefined p2是实例对象,不是函数对象,是没有prototype属性滴
console.log(Person.constructor)//Function 一个空函数
console.log(Person.prototype)
//打印出Person.prototype这个对象里所有的方法和属性
console.log(Person.prototype.constructor)//Person
console.log(Person.prototype.__proto__)
//Person.prototype是对象,所以输出:Object.prototype
console.log(Person.__proto__)//Function.prototype
console.log(Function.prototype.__proto__)//Object.prototype
console.log(Function.__proto__)//Function.prototype
console.log(Object.__proto__)//Function.prototype
console.log(Object.prototype.__proto__)//null
问题7:
function A() {
B = function () { console.log(10) }
return this
};
A.B = function () {
console.log(20)
};
A.prototype.B = function () {
console.log(30)
};
var B = function () {
console.log(40)
};
function B() {
console.log(50)
}
A.B() // 20
B() // 40
A().B() // 10
B() // 10
new A.B() // 20
new A().B() // 30
答案7解析:
A.B() // answer 20 【原型与原型链】
// 在`A`的原型对象中查找是否有`B`函数并且调用,这里并未执行`A`函数。
// A.B = function () {console.log(20)};
// 在A的原型对象中添加了`B`函数,停止查找,所以答案为 20
B() // answer 40 【函数表达式和函数声明】
// var B = function () {console.log(40)}
// function B() {console.log(50)}
// 同名 -> 函数提升会 > 变量提升
// 换言之 同名的函数表达式和函数声明同时存在时 总是执行表达式
A().B() // answer 10 【函数表达式和函数声明】
// A() 执行函数A ==> 1.变量B重新赋值函数 2.返回this(window)
// .B() 执行全局下的B函数 已经被重新赋值 所以输出10
B() // answer 10
// 上面的代码执行过A函数了,此时全局下的B函数输出10
new A.B() // answer 20【函数表达式和函数声明】
// new 执行了 A.B = function () {console.log(20)};
new A().B() // answer 30
// new 执行构造函数 A ,全局变量 B 重新赋值函数10
// 此时A() 指针指向哪里?
// 首先要知道 new 做了什么事?
// ==> 创建空对象objA objA.__proto__ = A.prototype
// .B() 在A的原型对象中查找 B; A.prototype 指向函数的原型对象
// A.prototype.B = function () {console.log(30)} 输出 30
未完待续。。。