关于构造函数和原型prototype对象的理解
构造函数
1.什么是构造函数
构造函数,主要用于对象创建的初始化,和new运算符一起用于创建对象,一个类可以有多个构造函数,因为函数名相同,所以只能通过参数的个数和类型不同进行区分,即构造函数的重构, 如果没有定义构造函数,那么该类会自动生成一个空参数的构造函数。
在javascript中,对象创建有二种方式:对象直接量和使用new表达式。
对象直接量是一个表达式,这个表示式每次运算都会创建和初始化一个新的对象,每次计算对象直接量的时候,也都会计算它的每个属性的值。
new表达式,配合构造函数使用,例如var person1 = new Person("wmm",30);
new操作符调用构造函数执行了以下几步:
a.首先创建一个空的person1对象 ------ var person1 = {};
b.将空对象person1的__proto__属性(其原型)指向构造函数的prototype对象, ------ person1.__proto__ = Person.prototype;
c.将构造函数的作用域赋值给person1对象,Person内的this指向实例化对象person1, -------- Person.call(person1);
d.返回新对象person1。 ------ return person1
2.构造函数和普通函数的区别
a.函数名称格式,构造函数一般首字母大写,而普通函数是一般首字母小写,使用驼峰式命名;
b.是否需要new调用, 构造函数需要new操作符调用,普通函数不需要;
c.this的指向,构造函数里this指向实例化对象,普通函数中this指向调用函数的对象,没对象调用时,默认指向window
d.返回值,构造函数默认返回值为实例化对象,不用return返回值,而普通函数通过return语句返回值。
prototype对象
每一个函数都有一个prototype属性,它指向一个对象的引用,每个实例化对象会从prototype指向的对象上继承属性。一旦原型对象上的属性发生了改变,实例化对象也会随之发生变化。
每一个对象都会在内部初始化一个属性(__prototype__),属性__proto__所指向的对象是它的原型对象,即
person1.__proto__ === Person.prototype。
当我们访问一个对象的属性时,如果对象内部找不到该属性,就会去实例化对象的属性__proto__指向的对象里面去找这个属性,__proto__里面有它自己的__proto__ 属性,然后一直找下去,直到找到为止。如果直到最顶层的Object.prototype还是找不到,则返回undefined.
所有一切对象的原型顶端,都是Object.prototype,Object.prototype的原型对象为null ,null对象没有自己的原型。
function Person(name){
this.name = name;
this.eat = function(){
console.log("food")
}
}
Person.prototype.age = "20";
Person.prototype.height = function(){
this.h = "160";
console.log(this.h);
}
var person1 = new Person("吴默默");
var person2 = new Person("wumomo");
每个实例化对象会继承构造函数的原型对象,实例化对象的属性__proto__指向的是原型对象,所以person1.__proto__ === person2.__proto__ === Person.prototype
prototype对象除了自定义属性和__proto__属性外,还有一个constructor属性,constructor属性指向的是它所在的构造函数,如下图:
实例化对象本身其实没有constructor属性,当找不到constructor属性时,就会根据person1.__proto__ 在其原型对象上查找。所以 person1.constructor === person1.__proto__.constructor === Person.prototype.constructor === Person
当重新定义prototype对象时,prototype对象原有的constructor属性会丢失,其constuctor属性会默认为Object(Person.prototype.constructor === Object)
构造函数和原型prototype的区别
每创建一个实例化对象,都要调用一次构造函数,当创建多个实例化方法时,就要调用多次构造函数,这可能会导致内存溢出,性能较差,而实例化对象会继承prototype对象上的属性,使用原型prototype定义时,不管实例化多少个对象,都只调用一次,所以最好的解决方式是公共的方法和属性可以放在prototype原型中,其他的放在构造函数内。
扩展:
isPrototypeOf() ----- 用于测试一个对象是否存在于另一个对象的原型链上
Person.prototype.isPrototypeOf(person1) // ture
instanceof ----- 一个对象是否是这个特定类或者是它的子类的一个实例,形式为 object instanceOf constructor
person1 instanceof Person // true
person3 instanceof Person // false
in运算符和hasOwnProperty() ------ 都是用来检测对象中是否存在某属性
in运算符 :只要通过对象能访问到属性就返回true,否则返回false
hasOwnProperty() : 只能检测到对象自身的属性,无法检查其原型链中是否具有该属性。
关于构造函数和原型prototype对象的理解的更多相关文章
- [js高手之路]一步步图解javascript的原型(prototype)对象,原型链
我们接着上文继续,我们通过原型方式,解决了多个实例的方法共享问题,接下来,我们就来搞清楚原型(prototype),原型链的来龙去脉. function CreateObj(uName) { this ...
- js中__proto__, property, prototype, 对象自身属性方法和原型中的属性方法的区别
__proto__: 这个属性是实例对象的属性,每个实例对象都有一个__proto__属性,这个属性指向实例化该实例的构造函数的原型对象(prototype). proterty:这个方法是对象的属性 ...
- 悟透Javascript之 原型prototype
构造函数的Prototype上定义的方法确实可以通过对象直接调用,而且代码是共享的.我表示我不懂.太难理解了,艹.在Javascript中,prototype不但能让对象共享自己的财富,而且proto ...
- JavaScript中的原型prototype和__proto__的区别及原型链概念
问题 初学js的同学,总是搞不清楚js中的原型是什么东西,看着控制台打印出来的一串串__proto__,迷惑不已. 例如我定义一个Person,创建一个实例p,并打印实例. function Pers ...
- JavaScript之面向对象学习二(原型属性对象与in操作符)获取对象中所有属性的方法
1.原型属性对象于in操作符之in单独使用 有两种方式使用in操作符:单独使用和在for-in循环中使用.在单独使用中,代码如下: function Person(){ } Person.protot ...
- JavaScript之prototype对象
简述prototype: 在js中,每个构造函数都有一个原型属性prototype,因为这个属性的值通常是一个对象,又叫原型对象!你不需要显式的去定义原型对象,因为每个构造函数都会一个原型属性,通常在 ...
- JS面向对像编程四—— prototype 对象
http://blog.csdn.net/fanwenjieok/article/details/54575560 大部分面向对象的编程语言,都是以“类”(class)作为对象体系的语法基础.Java ...
- Javascript面向对象——创建对象、构造函数的原型
Javascript面向对象--创建对象.构造函数的原型 其实:JavaScript中的创建类,就是创建一个构造函数,在创建对象时用到new这个关键字, 一.创建对象 1.函数创建对象 functio ...
- 构造函数、原型对象prototype、实例、隐式原型__proto__的理解
(欢迎一起探讨,如果有什么地方写的不准确或是不正确也欢迎大家指出来~) PS: 内容中的__proto__可能会被markdown语法导致显示为proto. 建议将构造函数中的方法都定义到构造函数的原 ...
随机推荐
- Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/boot/context/embedded/ServletRegistrationBean
异常信息 2017-09-02 18:06:37.223 [main] ERROR o.s.boot.SpringApplication - Application startup failed ja ...
- 安装Oracle之后在DOS命令下不能使用sqlplus命令启动Oracle?
就像完成安装JDK后需要给系统配置环境变量JAVA_HOME和PATH,以便让系统认识在JDK里面的Javac命令.同样的,安装Oracle也需要这么一个过程.在正常情况下安装Oracle时系统安装程 ...
- 《修改代码的艺术》【PDF】下载
<修改代码的艺术>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382309 内容简介 <修改代码的艺术>针对大型的. ...
- iOS开发--数据库管理CoreData的使用
CoreData是iOS5后,苹果提供的原生的用于对象化管理数据并且持久化的框架.CoreData本质上是将底层数据库封装成对象进行管理.但数据库实际上只是CoreData的一个功能,并不是全部功能. ...
- Docker Stack 集群部属服务
Docker越来越成熟,功能也越来越强大.使用Dokcer Stack做服务集群也是非常的方便,docker 自己就提供了负载功能,感觉很方便,就想给大家分享一下,做一个简单的教程. 环境 我是用了两 ...
- oracle初级(续)
有志者.事竟成,破釜沉舟,百二秦关终属楚: 苦心人.天不负,卧薪尝胆,三千越甲可吞吴. oracle基本简单的用法,之前的笔记稍作整理一下,希望对各位有用,如有问题可在下方留言,所有SQL都是经过or ...
- JSP和JavaBean总结
JSP JSP全名为Java Server Pages,即java服务器页面,其根本是一个简化的Servlet设计.它是在传统的网页HTML文件中插入Java代码,从而形成JSP文件. JSP注释分为 ...
- arcgis api for js热力图优化篇-不依赖地图服务
前面我写过一篇文章,介绍如何实现arcgis api的热力图效果,但是依赖arcgis server发布的地图服务来获取热力图的数据源.实际应用中,很多业务数据来源数据库,并不一定是从地图服务来获取的 ...
- AO之Addins开发[杂谈1] Toolbar中添加一条分割线
在XML代码中,给Item添加separator属性,需要从哪里打分割线,就将其设置为true即可.如下图所示: 如紫色框住的灰色竖线所示. 默认separator属性是false的,这个小东西极其隐 ...
- 利用generator自动生成model(实体)、dao(接口)、mapper(映射)
1 在MySQL数据库中创建相应的表 /* Navicat MySQL Data Transfer Source Server : 虚拟机_zeus01 Source Server Version : ...