面试复习js原型,原型链与new关键字原理

12 篇文章 1 订阅

创建对象可以用
1.object构造函数方法

person=new Object();
person.firstname="Bill";
person.lastname="Gates";
person.age=56;
person.eyecolor="blue";

2.对象字面量

var person ={
name:xxx,
...
}

上述两种方法都会产生大量重复的代码,解决该问题可抽象创建具体对象的过程(因为js在没有类的概念,所以用函数来封装)
3.工厂模式

function a(name){
  var b = new object();
    b.name = name;
    b.say = function(){
        alert(this.name);
    }   
       return b    
}

缺陷:创建两个完成同样任务的function实例没有必要,改进:

4.构造函数方法

function person(firstname,lastname,age,eyecolor)
{
this.firstname=firstname;
this.lastname=lastname;
this.age=age;
this.eyecolor=eyecolor;

this.changeName=changeName;
function changeName(name)
{
this.lastname=name;
}
}

缺陷:如果对象有多个方法就需要定义多个全局函数,就没有封装性可言了,改进

5.原型模式

每个函数都有一个Prototype(原型属性),这个属性是一个指针,指向一个对象。
使用原型对象的好处就是让所有对象实例共享它所包含的属性和方法。换句话说:不必在构造函数中定义对象实例的信息,而是可以把这些信息添加到原型链中。

function Person(){  
}

Person.prototype.name = "bill";
Person.prototype.address = "GuangZhou";
Person.prototype.sayName = function (){
       alert(this.name);  
}

var person1 = new Person();
 
//测试代码
alert(person1.name);   // bill
person1.sayName();    //bill

每个函数都有 prototype 属性,除了 Function.prototype.bind(),该属性指向原型。
每个对象都有 proto 属性,指向了创建该对象的构造函数的原型。其实这个属性指向了 [[prototype]],但是 [[prototype]] 是内部属性,我们并不能访问到,所以使用 proto 来访问。

对象可以通过 proto 来寻找不属于该对象的属性,proto 将对象连接起来组成了原型链。
原型、构造函数、实例三者之间的关系
在这里插入图片描述

  • 1、构造函数通过 new 生成实例

  • 2、构造函数也是函数,构造函数的prototype指向原型。(所有的函数有prototype属性,但实例没有 prototype属性)

  • 3、原型对象中有 constructor,指向该原型的构造函数。

  • 4、实例的__proto__指向原型。也就是说,Foo.__proto__ === M.prototype

  • 声明:所有的引用类型(数组、对象、函数)都有__proto__这个属性。

    Foo.__proto__ === Function.prototype的结果为true,说明Foo这个普通的函数,是Function构造函数的一个实例。

原型链

看一下什么是原型链。

原型链就是通过原型对象,原型链与实例之间组成的链条。

原型链的基本原理:任何一个实例,通过原型链,找到它上面的原型,该原型对象中的方法和属性,可以被所有的原型实例共享。

Object是原型链的顶端。

原型可以起到继承的作用。原型里的方法都可以被不同的实例共享:

原型链的关键:在访问一个实例的时候,如果实例本身没找到此方法或属性,就往原型上找。如果还是找不到,继续往上一级的原型上找。

通过原型理解instantceOfnew

instanceof的原理

instanceof作用:用于判断实例属于哪个构造函数

instanceof原理:判断实例对象的__proto__属性,和构造函数的prototype属性,是否为同一个引用(是否指向同一个地址)。

注意1:虽然说,实例是由构造函数 new 出来的,但是实例的__proto__属性引用的是构造函数的prototype。也就是说,实例的__proto__属性与构造函数本身无关。

注意2:在原型链上,原型的上面可能还会有原型,以此类推往上走,继续找__proto__属性。这条链上如果能找到, instanceof 的返回结果也是 true。

比如说:

  • foo instance of Foo的结果为true,因为foo.__proto__ === M.prototype为true。
  • foo instance of Objecet的结果也为true,因为Foo.prototype.__proto__ === Object.prototype为true。

但我们不能轻易的说:foo 一定是 由Object创建的实例。这句话是错误的。我们来看下一个问题就明白了。

分析一个问题

问题:已知A继承了B,B继承了C。怎么判断 a 是由A直接生成的实例,还是B直接生成的实例呢?还是C直接生成的实例呢?

分析:这就要用到原型的constructor属性了。

  • foo.__proto__.constructor === M的结果为true,但是 foo.__proto__.constructor === Object的结果为false。

所以,用 consturctor判断就比用 instanceof判断,更为严谨。

new 运算符

当new Foo()时发生了什么:

(1)创建一个新的空对象实例

(2)将此空对象的隐式原型指向其构造函数的显示原型。

(3)执行构造函数(传入相应的参数,如果没有参数就不用传),同时 this 指向这个新实例。

(4)如果返回值是一个新对象,那么直接返回该对象;如果无返回值或者返回一个非对象值,那么就将步骤(1)创建的对象返回。

function create() {
    // 创建一个空的对象
    let obj = new Object()
    // 获得构造函数
    let Con = [].shift.call(arguments)
    // 链接到原型
    obj.__proto__ = Con.prototype
    // 绑定 this,执行构造函数
    let result = Con.apply(obj, arguments)
    // 确保 new 出来的是个对象
    return typeof result === 'object' ? result : obj
}

参考文章
https://baijiahao.baidu.com/sid=1615168823913070039&wfr=spider&for=pc
https://yuchengkai.cn/docs/frontend/#new

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值