原型链类

本文是学习慕课网上课程前端跳槽面试必备技巧的学习笔记,便于之后复习。

从以下几个方面介绍原型链:

  1. 创建对象有几种方法
  2. 原型、构造函数、实例、原型链
  3. instanceof的原理
  4. new运算符

1.创建对象的方法

相应代码:

<script type="text/javascript">
    // 方式一:字面量
    var o1 = {name: 'o1'};
    var o2 = new Object({name:'o2'});

    // 方式二:通过构造函数
    var M = function(name){this.name = name;};
    var o3 = new M('o3');

    // 方式三:Object.create
    var p = {name: 'o4'};
    var o4 = Object.create(p);
    
    console.log(o1);
    console.log(o2);
    console.log(o3);
    console.log(o4);
</script>

运行效果如下图:

每种创建方式,创建出来的对象也不相同。

2.原型、构造函数、实例、原型链

什么是原型对象?实例?构造函数?

先看一段代码:

var M = function (name) { this.name = name; }
var o3 = new M('o3')

任何通过new操作后的函数就是构造函数,构造函数也是函数。

实例就是对象,在本例中o3就是实例,M是构造函数。

实例通过new一个构造函数生成。

实例的__protpo__指向的是原型对象。

实例的构造函数的prototype也是指向原型对象。

原型对象的constructor(构造器)指向的是构造函数。//原型对象用构造器区分被那个构造函数所引用

 

什么是原型链呢?

       简单理解就是原型组成的链,实例对象的__proto__是它的原型,而原型也是一个对象,也有__proto__属性,原型的__proto__又是原型的原型,就这样可以一直通过__proto__向上找,这就是原型链,当向上找找到Object的原型的时候,这条原型链就算到头了。

原型对象和实例之间有什么作用呢?

通过构造函数创建出很多属性和方法,实例可以共用这些属性和方法,当多个实例共用方法时,给每个实例都去添加方法并不是一个明智的选择。这时就该用上原型了。在实例的原型对象上添加一个方法,这个原型对象的所有实例便都有了这个方法。

代码举例:

<script type="text/javascript">
    // 方式二:通过构造函数
    var M = function(name){this.name = name;};
    var o3 = new M('o3');
    var o5 = new M('o5 ');

    // 在M.prototype 即原型对象 上增加一个方法say o3和o5均可以访问到
    M.prototype.say = function () {
        console.log('say');
    }
    o3.say();
    o5.say();

    // 在o3.__proto__ 即原型对象 上增加一个方法say1 o3和o5均可以访问到
    o3.__proto__.say1 = function () {
        console.log('say1');
    }

    o3.say1();
    o5.say1();
</script>

 

按照JS引擎的分析方式,在访问一个实例的属性的时候,现在实例本身中找,如果没找到就去它的原型中找,还没找到就再往上找,直到找到。这就是原型链。

补充:

1).只有函数有prototype,对象是没有prototype的。

2).对象有__proto__,但是函数也是有__proto__的,因为函数也是对象。函数的__proto__指向的是Function.prototype。也就是说普通函数是Function这个构造函数的一个实例。

3.instanceof的原理?

 

instanceof是判断实例对象的__proto__和生成该实例的构造函数的prototype是不是引用同一个地址。

仍是上一段代码

注意:实例的instanceof在比较的时候,与原型链上向上找到的构造函数相比都是true。

那怎么判断实例是由哪个构造函数生成的呢?

这时候就要用到constructor(构造器)了。实例的原型的构造器指向构造函数 obj.__proto__.constructor

4.new运算符工作原理?

 

new运算符的工作原理:

  1. 一个新对象被创建,新对象继承自foo.prototype      // foo为构造函数
  2. 构造函数被执行。执行时,相应的传参会被传入,同时上下文(this)会被指定为这个新实例。在foo不传参的情况下 new foo等同于new foo()
  3. 如果构造函数返回了一个‘对象’,这个对象会取代整个new出来的结果
  4. 如果构造函数没有返回对象,那么new出来的结果为步骤1创建的对象

用代码模拟new运算符:

 <script type="text/javascript">
        // 模拟new 运算符
	var new1 = function (func) {
	    // 1 创建空对象 空对象关联构造函数的原型对象
	    var o = Object.create(func.prototype); 
	    // 2 执行构造函数 改变this的指向
	    var k = func.call(o);
	    // 3 判断构造函数的运行结果是否为对象类型
	    if(typeof k === 'object'){	
	    	// 是 返回k
	    	return k
	    }else{
	    	// 不是 返回构造函数的执行结果
	    	return o
	    }
    }

    var M = function(name){this.name = name;};
    var o3 = new M('o3');
    var o5 = new M('o5 ');
</script>

通过上图我们可以看出,手动编写的new1和new运算符是一样的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值