专栏首页前端技术总结JS基础知识总结(三):原型、原型链
原创

JS基础知识总结(三):原型、原型链

上一篇JS基础知识总结(二)主要了介绍深拷贝、浅拷贝的基础知识,本文将介绍JS原型、原型链的有关内容。

1.原型

(1)所有的引用类型(对象、数组、函数),除了null,都具有对象特性,可自由扩展属性;

(2)所有的引用类型(对象、数组、函数)都有一个__proto__属性,属性值是一个普通的对象;

(3)所有的引用类型(对象、数组、函数)的__proto__属性值,指向它的构造函数的prototype属性值;

(4)所有的函数,都有一个prototype属性,属性值也是一个普通的对象

示例:

            //1,所有的引用类型可自由扩展属性
            var obj = {};
            var arr = [];
            function fn() { };
            obj.a = 1;
            arr.a = 1;
            fn.a = 1;
            console.log('obj', obj)
            console.log('arr', arr)
            console.log('fn.a', fn.a)

            //2,所有的引用类型都有一个_proto_属性
            console.log('obj.__proto__', obj.__proto__)
            console.log('arr._proto_', arr.__proto__)
            console.log('fn._proto_', fn.__proto__)
            
            //4,所有的函数,都有一个prototype熟悉,属性值是一个对象
            console.log('fn.prototype', fn.prototype)

            //3,所有的引用类型的_proto属性值,指向它的构造函数的prototype属性值
            console.log(obj.__proto__ === Object.prototype) //true

对于示例中的obj,在控制台打印出来可以发现,它除了具有属性a外,还有一个__proto__属性,属性值是一个普通对象:

当试图得到一个对象的某个属性时,如果该对象没有这个属性,就会去该属性的_proto_(即该对象的构造函数的prototype)中找。

2.原型链

示例:

             //构造函数
            function Person(name) {
                this.name = name;
            }
            Person.prototype.showName = function () {
                alert(this.name);
            }
            //创建实例
            var person1 = new Person('peter');
            person1.printName = function () {
                console.log('name is:', this.name);
            }
           
            person1.printName()
            person1.showName()
            person1.toString();
            
            console.log('Person.prototype', Person.prototype)
            console.log('Person.prototype.__proto__', Person.prototype.__proto__)

person1本身有printName,但当试图执行person1.showName时,由于对象本身没有这个属性时,那么会去它的__proto__,即它的构造函数的prototype中去寻找。在上述示例中,person1.showName就会去它的构造函数Person的prototype中去寻找,就会找到Person.prototype.showName。

当试图执行person1.toString时,由于person1本身没有toString,因此去person1.__proto__(即Person.prototype)中去找,发现没有找到,继续往上找。person1.__proto__.__proto__(即Person.prototype.__proto__)中去找,Person.prototype就是一个普通对象,因此,Person.prototype.__proto__就是Object.prototype,在这里可以找到toString()。即person1.toString最终向上找到了Object.prototype.toString。

整个过程:

person1没有找到toString,往上找;

person1.__proto__即Person.prototype,没有找到toString,继续往上找;

person1.__proto__.__proto__即Person.prototype.__proto__,即Object.prototype,可以找到toString:

这样通过__.proto__一直往上找,就是一个链式结构,即“原型链”。如果找到原型链的最上册都没有找到,就会返回undefined,宣布失败。

上述2原型链的示例中,在执行person1.printName()、person1.showName()时,this是什么呢?

所有从原型或更高级原型中得到的方法,this指向当前触发事件执行的对象,因此这里printName()、showName中的this,都是person1

下面祭出这张图,参考

所有的对象都可以通过__proto__找到Object,Object是所有对象的基类(父类)

所有的函数都可以通过__proto__找到Function,Function是所有函数的基类(父类)

所有的引用类型默认都继承了Object,这个继承是通过原型链实现的;

所有的函数的默认原型也是Object的实例,因此默认原型都会包含一个内部的指针,指向Object.prototype。这也是自定义类型都会继承toString()、valueOf()等默认方法的根本原因。

那么如何判断这个属性是对象本身的属性呢?可以使用hasOwnProperty():

还是继续使用上述1中的示例:

console.log('person1.hasOwnProperty(printName)', person1.hasOwnProperty("printName")) //true
console.log('person1.hasOwnProperty(showName)', person1.hasOwnProperty("showName")) //false

3.小结

本篇JS基础知识总结,主要是分别结合一些示例,介绍了原型、原型链的基本知识。如有问题,欢迎指正。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 小结ES6基本知识点(四):数组的扩展

    ES6初学者,通过阅读本文可对ES6知识点有个大体的概念,强烈建议阅读阮一峰大大的ES6入门

    前端林子
  • 小结ES6基本知识点(一)

    ES6初学者,通过阅读本文可对ES6知识点有个大体的概念,强烈建议阅读阮一峰大大的ES6入门。

    前端林子
  • 如何在webpack中设置favicon--webpack入门教程(四)

    本文主要想介绍前端webpack打包中,与favicon图标相关的配置。包括在html-webpack-plugin中设置favicon,和自定义favicon...

    前端林子
  • JS示例20-如何读取父节点parentNode

    专注APP开发
  • 原 each()、map()

    作者:汪娇娇 日期:2016.9.1 如果说到某个元素的开关事件,第一反应那就是用一个变量做标记,比如flag,为1时开,为0时关,这是很简单的。下面我将以li...

    jojo
  • Python List 删除元素

    py3study
  • 列表,for循环相关.

    py3study
  • FCoin公开资产透明计划,开始打破全球交易所格局

    说到FCoin,先得从创始人张健说起。他从2013年进入区块链行业,2014年至2016年在彼时全球最大的交易所火币网担任CTO,离开后一直专注于区块链底层技术...

    区块链领域
  • Python 操作List

    总结:第一种方方法思路比较清晰,就是运算符的重载;第二种方法比较简洁,但会覆盖原始list;第三种方法功能比较强大,可以将一个列表插入另一个列表的任意位置

    周小董
  • 简单搭建SpringBoot项目

      Spring Boot 本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。也就是说,它并不是...

    java之旅

扫码关注云+社区

领取腾讯云代金券