面试翻车现场?对象靠原型链上演 “逆风翻盘” 名场面(上)

91 阅读3分钟

好了,“是你,是你,一定是你”(bgm响起),OK,停————

是谁为面试被问原型链知识慌得一批,陷入 “听我说,谢谢你,因为有你,挂得很彻底” 的 emo 得不能自已时,恨不得抠出三室一厅的时候,通过本篇文章,你就可以展示出“姐就是女王,自信放光芒”的高光时刻了。这篇文章就带你深入地去理解原型和原型链。

面试官问你:"了解原型链吗?"

我:"了解"

面试官:"那你说一下?"

我:"就是原型组成的链"

面试官:"深入的说一下??!"

我:"..."

真给你机会了,你又不重用了??!好了,我们开始进入正题~

原型是什么

每个函数都会有一个特殊的属性property,而这个属性指向的是一个对象。那这个属性就是由这个函数作为构造函数创建出来所有对象的原型。

那原型的作用是什么?

用于访问属性和方法。

能回答出上述的,在这道题目上其实已经得到了70%的满意度了。

那我们来说说你不知道的原型特性

我们刚刚也说了,每个函数都会有一个property,那我们来看数据对象的原型:

普通对象

const obj = {};
console.log(obj.__proto__ === Object.prototype); 

输出:true 从这个结果我们可以得知,普通对象的原型是Object.prototype。这时候,有些同学可能会问:那__proto__是什么?每个对象在创建之后,就会携带一个__proto__参数(property),如果没有那么就会接受default property作为他可以继承的对象。

那既然都携带了这个属性,是不是代表着我更改_proto_指向,就能更改其原型? 答案是对的。

const A = {
   like:function(){
   console.log('我喜欢小美');
   },
   unlike:function(){
   console.log('我不喜欢男的');
   }
}
const B = {
   like:function(){
   console.log('我喜欢小帅');
   },
   unlike:function(){
   console.log('我不喜欢小明');
   }
}
B.__proto__ = A;

// 测试调用
B.like();
B.unlike();    

A是小明,B是小美。来,你说说,小美到底喜欢谁?

image.png 好了,那我们之前明明说了呀,__proto__指向其他原型呀,为啥小美还是喜欢小帅。那我们就不得不提到一个词叫做继承。

你原先有个儿子,现在忽然有个儿子说要做你儿子。

那你的儿子是谁?

肯定是自己的亲儿子优先呀。我没有儿子,但有人想认我当爹,我肯定喜欢呀。

由此得出结论,原型是具有继承性的,继承这个对象之后便可以使用其属性和方法。也可以理解为,通过__proto__属性,连接了A和B,构造了一个更大的共享数据库,里面有A的属性方法和B的属性方法。

但是,虽然可以用__proto__去更改原型指向,但是不是很推荐喔? 中国体质的宝宝更适合于用Object.setPrototypeOf()这个方法来设置其原型。

Object.setPrototypeOf(B,A)

数组对象

const arr = []; 
console.log(arr.__proto__ === Array.prototype); 
// 输出: true 
console.log(arr.__proto__.__proto__ === Object.prototype); 
// 输出: true

数组的原型是Array.prototype,Array.prototype的原型是Object.prototype

函数对象

function func() {} 
console.log(func.__proto__ === Function.prototype);
// 输出: true
console.log(func.__proto__.__proto__ === Object.prototype);
// 输出: true

函数对象的原型是 Function.prototypeFunction.prototype 的原型是 Object.prototype

日期对象

function func() {}
console.log(func.__proto__ === Function.prototype); 
// 输出: true 
console.log(func.__proto__.__proto__ === Object.prototype);
// 输出: true

日期对象的原型是 Date.prototypeDate.prototype 的原型是 Object.prototype

字符串对象

const strObj = new String('hello'); console.log(strObj.__proto__ === String.prototype); 
// 输出: true console.log(strObj.__proto__.__proto__ === Object.prototype); 
// 输出: true const str = 'hello'; console.log(String.prototype.isPrototypeOf(str));
// 输出: true

字符串对象原型是 String.prototypeString.prototype 的原型是 Object.prototype

布尔对象

const boolObj = new Boolean(true); console.log(boolObj.__proto__ === Boolean.prototype); // 输出: true 
console.log(boolObj.__proto__.__proto__ === Object.prototype); 
// 输出: true const bool = true; console.log(Boolean.prototype.isPrototypeOf(bool));
// 输出: true

布尔对象原型是 Boolean.prototypeBoolean.prototype 的原型是 Object.prototype

数字对象

const numObj = new Number(10); console.log(numObj.__proto__ === Number.prototype); 
// 输出: true 
console.log(numObj.__proto__.__proto__ === Object.prototype);
// 输出: true const num = 10; console.log(Number.prototype.isPrototypeOf(num)); 
// 这里利用 isPrototypeOf 方法判断,输出: true

数字对象原型是 Number.prototypeNumber.prototype 的原型是 Object.prototype

写的不好,请海量~