前端面试题
-
什么是原型、原型链
-
它们有什么特点
-
它们能做什么
-
怎么确定它们的关系
1、对象的分类:普通对象 与 函数对象
在JS 中,万物皆对象,但是对象也是有区别的,分别为 普通对象 和 函数对象,Object, Function, Array, String, Number, Boolean, Date 等都是 JS 内置的函数对象。
对象的分类:普通对象 与 函数对象
普通对象
{
//普通对象
let o1={
name:'tom',
age:20,
}
let o2=new Object();
o2.name='xy'
function F1(n,s){
this.name=n
this.sex=s
}
let o3=new F1('xy','男');
console.log(typeof o1,o1);
console.log(typeof o2,o2);
console.log(typeof o3,o3);
}
预览:
函数对象
{
//函数对象
function f1(a,b){
return a+b;
}
var f2=function(x,y){
return x+y
}
let str='return'+'`hello ${name}`';
let f3=new Function('name',str);
// f3('小马')
// console.log(f3('小马'));
console.log(typeof f1);
console.log(typeof f2);
console.log(typeof f3);
}
预览:
{
//内置对象
// Object, Function, Array, String, Number, Boolean, Date 等都是 JS 内置的函数对象
console.log('-------');
console.log(typeof Date);
console.log(typeof Function);
console.log(typeof Array);
console.log(typeof Number);
console.log(typeof Boolean);
console.log(typeof String);
console.log(typeof Object);
}
预览:
2、原型
2.1 prototype原型的概念
每一个 JavaScript 对象(null 除外)在创建的时候就会与之关联一个对象,这个对象就是我们所说的原型,它包含了特定类型的所有实例共享的属性和方法,每一个对象都会从原型继承这些属性、方法。所以,原型对象的好处是:可以让所有的实例对象共享它所包含的属性和方法。
2.2 prototype原型分类:显示原型和隐式原型
每个函数都有一个prototype属性,被称为显示原型每个实例对象都会有__proto__
_属性,其被称为隐式原型每一个实例对象的隐式原型__proto__
属性指向自身构造函数的显式原型prototype每个prototype原型都有一个constructor(看次chua克特)属性,指向它关联的构造函数。
每个对象,都有一个prototype属性,被称为原型
{
//数组
let arr=[1,2,3];
console.log(arr,typeof arr);
}
{
//对象
let o={
name:'tom',
age:18
}
console.log(o,typeof o);
}
预览:
通过构造函数,去分析 实例化对象身上的原型的使用
// 创建构造函数
// 为了与普通函数区分---构造函数的名称的首字母要求大写
// 构造函数的两个特点:
// 1.函数体内使用this关键字,this代表所要生成的实例对象;
// 2.生成对象时,必须使用new关键字。
function Person(name,age){
this.name = name;
this.age = age;
}
console.log(Person);
console.log(typeof Person);
// 每个对象身上,都有一个prototype,我们称它叫原型对象(原型)
console.log(Person.prototype);
预览:
2.3 prototype原型的特点
每一个对象都会从原型继承这些属性、方法
原型对象的好处是:可以让所有的实例对象 共享它 所包含的属性和方法 !!
实例化对象 可以 继承使用 原型上 包含的属性和方法。
(实例化对象 和原型 直接 体现了 “继承性”)。
原型对象的主要作用是 :用于继承 。
{
//实例化对象共享 属性和方法
function Person(name,age){
this.name=name;
this.age=age;
Person.prototype.sex='男';
Person.prototype.job='开发工程师'
Person.prototype.sayName=function(){
console.log(this.name);
}
}
//实例化对象
let p1=new Person('xy',22);
console.log(p1);
//
p1.sayName()
console.log(p1.sex);
let p2=new Person('xm',20)
console.log(p2);
p2.sayName()
console.log(p2.job);
}
预览:
2.4__proto__
隐式原型
隐式原型是利用__proto__
属性查找原型,这个属性 指向 当前对象的构造函数的原型对象,这个属性是对象类型数据的属性,所以可以在实例对象上面使用。
( 隐式原型 出现 实例对象上, 用它 追溯 原型。)
javascript对象中的__proto__
属性 (隐式原型)
{
//__proto__是js对象的属性(隐式原型),本身是一个对象
//普通对象
let o1={a:1};
console.log(o1);
console.log(o1.__proto__);
console.log(typeof o1.__proto__);
console.log(o1.__proto__===Object.prototype);
}
{
//内置顶层函数对象
let date =new Date()
console.log(date.__proto__);
}
{
function Person(name,age){
this.name=name;
this.age=age
}
let p1=new Person('fbfb',131)
console.log(p1.__proto__);
console.log(p1.__proto__ === Person.prototype);
}
预览:
constructor、prototype和proto之间的关系
2.5 constructor属性
原型对象(原型)来说,它有个constructor属性,指向它的构造函数 。
constructor
属性是对象拥有的属性,它是从一个对象指向一个函数,含义就是指向该对象的构造函数,每个对象都有构造函数(本身拥有或继承而来)
{
//原型对象中的constructor属性
console.log(Array.prototype);
console.log(Array.prototype.constructor);
if(Array.prototype.constructor===Array){
console.log('我是Array数组对象');
}
}
{
//构造函数
function Foo(name){
this.name=name;
Foo.prototype.color='orange';
}
//实例化对象
let f1=new Foo('桃子')
console.log(f1);
// console.log(Foo.prototype.color)
console.log(f1.color);
console.log(f1.__proto__===Foo.prototype);
}
预览: