【js基础】javascript中的原型总结
2017-07-26 23:03
656 查看
前言:学习js有段时间,感觉写代码时,很少用到。看懂了过段时间又忘记了。网上关于js原型链和闭包资料满天飞,可见他们的重要性吧。暑假在家看完javascrit高级程序设计第六章,现在做一个笔记,不然估计过几天又忘记了。希望熟悉之后,以后有意识的用一下这些特性。我对于原型的理解都是基于c语言指针和内存知识类比的,可以作为参考,但不保证正确。
这篇博客new出来的对象全部称为对象实例 用于创建对象实例的函数全部称为构造函数 构造函数的原型称为原型对象。
不像java,js中没有类这样显示的定义。所以对象实例的创建都通过函数的封装。看下面栗子:
这种模式虽然解决了创建多个相似对象问题,却没有解决对象类型问题。主要是这样创建的对象示例无法用js中的对象类型检测手段检测。即
而且工厂模式创建对象,很明显是通过函数的显现调用手段进行的。过程如下,在执行var person1=Person(“Tom”,18,”男”);语句时,调用Peson函数,执行Person函数时,先创建一块和Object对象所占内存一样大的内存,然后变量o执行创建这一块内存的地址。o即为这一块内存的地址。然后在这块内存中加入name,age,sex等对象属性值。然后返回对象o的值给person1,即person1的值为创建的那一块内存的地址。最后销毁o的值。但分配的内存不会被销毁。只有当js的垃圾回收机制检测到这一块内存没有用时才会自动释放。
构造函数在创建一个对象实例时,先创建一块和构造函数 一样大的内存。然后再调用构造函数,在此过程中this指向该构造函数的实例。即this指向新对象实例。然后执行构造函数里面的代码。其中通过this来向创建的内存中加入新的属性。
但构造函数模式也有缺点:如上例每个对象实例创建时都要分配一块内存,这是无可厚非的,但是在创建每一个对象实例的过程中会调用构造函数Person,在执行构造函数里面的代码
时,每一个对象实例在添加sayConntent属性时又要再分配一块小内存,但是这些内存中的内容却一样。可以验证:
这样很浪费资源。
所以我们可以这样做:
这样的话,每个对象实例的属性sayContent都执行函数function sayContent的地址。可以验证
但是这样做又破坏我们封装构造函数来创建对象实例的初衷。
所以原型模式登场。。。原型出来啦。。。。。。。。
先上原理图:
解释:每当我们创建一个构造函数时,这个构造函数都会默认取得一个新的属性prototype,这个属性本质上是一个指针,指向函数的原型对象。。默认状态下,每个原型对象都取得一个默认属性constructor,其本质上也是一个指针,constructor指向prototype属性所在的函数(不一定指向创建的函数,当创建的函数的prototype属性被重写,就不指向创建的函数)。而由构造函数创建的对象实例都会默认取得一个 [b]___proto___ 属性,他本质上也是一个指针,他指向构造函数的原型对象,不指向构造函数。[/b]
多个对象公用一个属性sayContent。上面其实为构造函数模式与原型模式混搭。这种方案在创建js对象实例时用得最多。
这篇博客new出来的对象全部称为对象实例 用于创建对象实例的函数全部称为构造函数 构造函数的原型称为原型对象。
不像java,js中没有类这样显示的定义。所以对象实例的创建都通过函数的封装。看下面栗子:
创建对象实例方法一:工厂模式
function Person(name,age,sex){ var o=new Object(); o.name=name; o.age=age; o.sex=sex; o.sayContent=function(){ alert("hello world"); }; return o; } var person1=Person("Tom",18,"男");
这种模式虽然解决了创建多个相似对象问题,却没有解决对象类型问题。主要是这样创建的对象示例无法用js中的对象类型检测手段检测。即
alert(typeof person1);//object alert(person1 instanceof Person);//false alert(person1.constructor==Person);//false
而且工厂模式创建对象,很明显是通过函数的显现调用手段进行的。过程如下,在执行var person1=Person(“Tom”,18,”男”);语句时,调用Peson函数,执行Person函数时,先创建一块和Object对象所占内存一样大的内存,然后变量o执行创建这一块内存的地址。o即为这一块内存的地址。然后在这块内存中加入name,age,sex等对象属性值。然后返回对象o的值给person1,即person1的值为创建的那一块内存的地址。最后销毁o的值。但分配的内存不会被销毁。只有当js的垃圾回收机制检测到这一块内存没有用时才会自动释放。
创建对象实例方法二:构造函数模式
构造函数模式克服工厂模式中不能检测创建对象实例的类型问题。function Person(name,age,sex){ this.name=name; this.age=age; this.sex=sex; this.sayContent=function(){ alert("hello world"); }; } var person2=new Person("Jerry",18,"女"); var person3=new Person("Nary",15,"女"); alert(person2 instanceof Person);//true alert(person2.constructor==Person);//true
构造函数在创建一个对象实例时,先创建一块和构造函数 一样大的内存。然后再调用构造函数,在此过程中this指向该构造函数的实例。即this指向新对象实例。然后执行构造函数里面的代码。其中通过this来向创建的内存中加入新的属性。
但构造函数模式也有缺点:如上例每个对象实例创建时都要分配一块内存,这是无可厚非的,但是在创建每一个对象实例的过程中会调用构造函数Person,在执行构造函数里面的代码
this.sayContent=function(){ alert("hello world"); }; 等价于 this.sayContent= new Function( alert("hello world"); );
时,每一个对象实例在添加sayConntent属性时又要再分配一块小内存,但是这些内存中的内容却一样。可以验证:
alert(person2.sayContent===person3.sayContent);//false
这样很浪费资源。
所以我们可以这样做:
function Person(name,age,sex){ this.name=name; this.age=age; this.sex=sex; this.sayContent=SayContent; } function SayConttent(){ alert("hello world"); } var person2=new Person("Jerry",18,"女"); var person3=new Person("Nary",15,"女"); alert(person2 instanceof Person);//true alert(person2.constructor==Person);//true
这样的话,每个对象实例的属性sayContent都执行函数function sayContent的地址。可以验证
alert(person2.sayContent===person3.sayContent);//true
但是这样做又破坏我们封装构造函数来创建对象实例的初衷。
所以原型模式登场。。。原型出来啦。。。。。。。。
创建对象实例方法三:原型模式
function Person(){ } Person.prototype.age=18; Person.prototype.sex="男"; Person.prototype.saycontent=function(){ alert("Hello World"); }; var person2=new Person(); var person3=new Person();
先上原理图:
解释:每当我们创建一个构造函数时,这个构造函数都会默认取得一个新的属性prototype,这个属性本质上是一个指针,指向函数的原型对象。。默认状态下,每个原型对象都取得一个默认属性constructor,其本质上也是一个指针,constructor指向prototype属性所在的函数(不一定指向创建的函数,当创建的函数的prototype属性被重写,就不指向创建的函数)。而由构造函数创建的对象实例都会默认取得一个 [b]___proto___ 属性,他本质上也是一个指针,他指向构造函数的原型对象,不指向构造函数。[/b]
function Person(name,age,sex){ this.name=name; this.age=age; this.sex=sex; } Person.prototype.sayContent=function(){ alert("hello world"); } var person2=new Person("Jerry",18,"女"); var person3=new Person("Nary",15,"女"); alert(person2.sayContent==person3.sayContent);//true
多个对象公用一个属性sayContent。上面其实为构造函数模式与原型模式混搭。这种方案在创建js对象实例时用得最多。
相关文章推荐
- js基础-JavaScript开发技巧总结
- JavaScript学习总结【2】JS基础
- [JS]视频总结-第二部分_JavaScript基础
- JavaScript学习总结三:js基于原型面向对象
- JavaScript学习总结三:js基于原型面向对象
- js基本知识点总结-----js函数基础
- 【javascript基础】 js判断flashplayer是否已安装,并显示flash player版本【转】
- js 基础总结
- javascript基础总结
- 总结---JavaScript基础DOM操作
- JS学习实例:JavaScript时钟及Date对象学习总结
- JavaScript学习总结【5】JS DOM
- JavaScript继承基础讲解(原型链、借用构造函数、混合模式、原型式继承、寄生式继承、寄生组合式继承)
- JavaScript之面向对象学习五(JS原生引用类型Array、Object、String等等)的原型对象介绍
- 【温故知新】——BABYLON.js基础·常用知识点总结
- JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模)
- Javascript DOM基础总结
- 面向对象JS基础讲解,工厂模式、构造函数模式、原型模式、混合模式、动态原型模式
- [js]javascript基础--通过看书笔记
- 【知识整理】javascript基础语法总结(1)——变量和数据类型