博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
javascript原型详解(1)
阅读量:4290 次
发布时间:2019-05-27

本文共 3995 字,大约阅读时间需要 13 分钟。

我们创建的每一个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。

原型对象实际就是一个构造函数的实例对象,与普通的实例对象没有什么本质上的区分,js中每一个对象都有一个原型对象。不过他比较特殊,该对象所包含的所有属性和方法能够供构造函数的所有实例共享,这就是其他语言所说的继承,而js通过原型对象来实现继承,简称原型集成。静态原型继承:Object.prototype.[method field]

首先,考虑以下代码用构造函数的方式来创建实例对象:

//构造函数方式function Person(name , age){
this.name = name ; this.age = age ; this.sayName = function(){
alert('我是姓名!')};}var p1 = new Person('z3',20);var p2 = new Person('z4',21);p1.sayName();p2.sayName();//alert(p1.sayName == p2.sayName); // false

sayName 是p1和p2都拥有的函数,但是却被创建了两次,属于两个完全不相同的函数。如果通过这种方式创建很多的对象,毫无疑问性能会大大降低。因此我们可以将该函数抽取出来让其只会编译一次,如下:

function Person(name , age){
this.name = name ; this.age = age ; //this.sayName = function(){alert('我是姓名!')}; this.sayName = sayName ; }function sayName(){
alert(this.name);}//alert(p1.sayName == p2.sayName); true

现在基本上满足了我们以上的需求,函数只会在多个对象之间创建一次,但是这个函数是全局的,可能会被其他对象引用到,这也不是我们的初衷,因此我们可以引入原型对象


prototype 创建每一个函数都有一个prototype属性,这个属性其实是一个指针,而这个指针总指向一个对象,这个对象的用途就是将特定的属性和方法包含在内,起到一个所有实例所共享的作用

function Person(){
}var obj = Person.prototype;//alert(typeof obj); //object (obj实际上就是Person构造函数)obj.name = 'z3';obj.age = 20 ; obj.sayName = function(){
alert(this.name);};var p1 = new Person();var p2 = new Person();//alert(p1.age); //20//alert(p2.age); //20//p1.sayName(); //z3//p2.sayName(); //z3//alert(p1.sayName == p2.sayName) //true//因此,我们做到了共享原型对象中定义的属性和方法

构造函数 原型对象 实例对象之间的关系:

//构造函数.prototype =  原型对象//原型对象.constructor = 构造函数//alert(obj.constructor);//原型对象.isPrototypeOf(实例对象)//alert(obj.isPrototypeOf(p1));

原型中一些重要的方法

function Person(){
}Person.prototype.name = 'z3'; Person.prototype.age = 20 ; Person.prototype.sayName = function(){
alert('我是原型对象的方法!')};
//ECMA5: Object.getPrototypeOf():根据实例对象获得原型对象//isPrototypeOf(new instance); 判断原型的方法var p1 = new Person();alert(p1.name); // z3 var prototypeObj = Object.getPrototypeOf(p1);alert(prototypeObj == Person.prototype); //truealert(Person.prototype.isPrototypeOf(p1)); //true
//每次代码读取一个对象的属性的时候: 首先会进行一次搜索:搜索实例对象里name的属性,看看有没有如果没有,再去p2的实例所对应的原型对象里去搜索name属性 如果有就返回 没有返回undefinedvar p2 = new Person();p2.name = 'w5';     // 实例对象的namedelete p2.name ;    alert(p2.name);     // 先删除实例中的属性,然后获得原型对象的name属性
//判断一个对象属性 是属于原型属性 还是属于实例属性//hasOwnProperty只判断对象的属性是否属于实例属性(不包括原型)var p3 = new Person();p3.name = 'z6';alert(p3.hasOwnProperty('name')); //truedelete p3.name;  alert(p3.hasOwnProperty('name')); //false//for in操作可以遍历出实例对象和原型对象的所有属性  因此可以使用in来判断for(var index in p1){    alert(index);   // name age sayName}var p1 = new Person();alert('name' in p1); // truevar p2 = new Person();p2.name = 'w3';alert('name' in p2); // true//因此可以综合判断出属性是否属于原型中function hasPrototypeProperty(object , name){
return !object.hasOwnProperty(name) && name in object ;}var p3 = new Person();p3.name = 'xiao A';alert(hasPrototypeProperty(p3,'name')); //false
// ECMA5新特性 Object.keys();拿到当前对象里的所有keys 返回一个数组var p1 = new Person();p1.name = 'z3';p1.age = 20 ; var attributes = Object.keys(p1);alert(attributes);   //name,agevar attributes2 = Object.keys(Person.prototype);alert(attributes2);   //name,age,sayName//ECMA5 constructor属性: 该属性是不能被枚举的[eable = false];Object.getOwnPropertyNames 枚举对象所有的属性 :不管该内部属性能否被枚举(不会包括原型对象)var attributes3 = Object.getOwnPropertyNames(Person.prototype);alert(attributes3);  //constructor,name,age,sayNamevar p1 = new Person();alert(Object.getOwnPropertyNames(p1));  //空
//ECMA5中的Object.defineProperty()方法可以为原型对象重新加入构造器function Person(){
}Person.prototype = { //constructor : Person , //必须得表示原型对象的构造器 name: 'z3' , age : 20 , job : '程序员' , say : function(){
alert('我是原型的函数!'); }};//如果不加constructor对象,则alert(Person.prototype.constructor)为Object;如果加入该行对象定义,可以满足我们的要求结果是Person,但是当我们进行for-in遍历的时候constructor对象也会被遍历出来,这跟实际的构造函数不可遍历有冲突,因此我们可以使用defineProperty来给原型对象重新设置构造器的方法Object.defineProperty(Person.prototype , 'constructor' , { enumerable : false , value : Person });//参数1 :重设构造器的对象//参数2:设置什么属性//参数3:options配置项

转载地址:http://mhrgi.baihongyu.com/

你可能感兴趣的文章
SEO基本功:站内优化的一些基本手段
查看>>
centos6系列和7系列如何对外开放80,3306端口号或者其他端口号
查看>>
为什么您宁愿吃生活的苦,也不愿吃学习的苦?为什么你不愿意去学习呢
查看>>
解决elasticsearch7.3版本安装过程中遇到的包括内存不够、线程不够等问题
查看>>
日常项目测试用例检查点(来自一线测试人员的吐血总结)
查看>>
网站建设之域名注册和域名备案
查看>>
解决bootstrap时间输入框总被浏览器记住的记录遮挡住的问题
查看>>
git将一个分支完全覆盖另外一个分支如:dev分支代码完全覆盖某一个开发分支
查看>>
elasticsearch7.3版本环境搭建(二)可视化管理后台kibana的安装和配置
查看>>
elasticsearch7.3版本环境搭建(三)可视化管理后台kibana的汉化(设置中文界面)
查看>>
记录一次DDos攻击实战
查看>>
分享一首小诗--《致程序员》
查看>>
为什么百度只抓取了首页而不抓取我的网站的内页的原因分析
查看>>
年薪170万的阿里P8级员工征婚有感--话说阿里真有钱,这员工要求的条件真多
查看>>
又是一年桂花飘香时,祝我们伟大的祖国70年华诞更加繁荣昌盛,祝大家国庆节快乐
查看>>
谷歌浏览器chrome即将在2020年底停止支持flash,我们程序员该怎么办
查看>>
如何将数据采集到 Elasticsearch 服务
查看>>
面试官:mysql表设计要注意什么?
查看>>
一些精致小众网站收集录
查看>>
计算机科学探秘之linux发展史
查看>>