注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

梦幻雪冰

技在手,能在身,思在脑,从容过生活——陈能堡

 
 
 

日志

 
 

JavaScript 高级开发-原型  

2014-10-21 20:39:31|  分类: JavaScript |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

JavaScript 高级开发-原型

欢迎学习交流-梦幻雪冰
【1】原型是什么东西?
JavaScript 高级开发-原型 - 梦幻雪冰 - 梦幻雪冰
     a、创建的每一个函数都有prototype属性,是一个指针,指向一个对象(原型对象)。
     b、属性prototype是函数作为构造函数时使用的,它引用的是作为整体对象类的原型对象(指向原型)。
     c、由这个构造函数创建的任何对象都会继承属性prototype引用的对象的所有属性和方法(原型对象里面的方法和属性)
画图辅助理解:
JavaScript 高级开发-原型 - 梦幻雪冰 - 梦幻雪冰
 注:图片下方的两个prototype是实例里面的属性

【2】原型的语法
构造函数名.prototype.XXX = XXX;

function Peo(name, job){

     this.name = name;
     Peo.prototype.job = job;
     Peo.prototype.say = function(){
          console.log("我的名字:" + this.name + " " + "我的工作:" + this.job);
     }
}
var peo1 = new Peo("梦幻雪冰", "前端开发");
console.log(peo1.say());
【输出】我的名字:梦幻雪冰  我的工作:前端开发
JavaScript 高级开发-原型 - 梦幻雪冰 - 梦幻雪冰欢迎学习交流-梦幻雪冰
继续添加一个实例

function Peo(name, job){
this.name = name;
Peo.prototype.job = job;
Peo.prototype.say = function(){
console.log("我的名字:" + this.name + " " + "我的工作:" + this.job);
}
}
var peo1 = new Peo("独行冰海", "教学主管");
var peo2 = new Peo("梦幻雪冰", "美工");
peo1.say();
peo2.say();

【输出】我的名字:独行冰海 我的工作:美工  我的名字:梦幻雪冰 我的工作:美工
【结果】为什么job的属性的值都是“美工”,之前的“前端开发”被覆盖了?
  使用原型对象的好处就是可以让所有对象的实例共享它所包含的属性和方法

【3】给实例对象新增加一个属性(与原型中的属性名字相同)

function Peo(name, job){

     Peo.prototype.name = name;
     Peo.prototype.job = job;
     Peo.prototype.say = function(){
          console.log("我的名字:" + this.name + " " + "我的工作:" + this.job);
     }
}

var peo1 = new Peo("xiaoxiao", "前端开发");
var peo2 = new Peo("xiao", "美工");
peo1.name = "lili";
peo1.say();
peo2.say();
console.log("新增加的属性:" + peo1.name);
console.log("原型对象的属性:" + peo2.name);
【输出】
我的名字:lili 我的工作:美工 
我的名字:xiao 我的工作:美工 
新增加的属性:lili 
原型对象的属性:xiao 
【结论】虽然可以通过对象实例访问原型中的值,但是切不能通过对象实例重写原型中的值。
【解析】类似作用域,就是在对象实例中寻找看有没有name该属性,如果有就不必再搜索原型了;如果不存在才会继续搜索原型
画图辅助理解:
JavaScript 高级开发-原型 - 梦幻雪冰 - 梦幻雪冰
 
  peo1添加属性之后JavaScript 高级开发-原型 - 梦幻雪冰 - 梦幻雪冰
JavaScript 高级开发-原型 - 梦幻雪冰 - 梦幻雪冰
 
【4】那么怎么检测属性是属于原型的还是属于实例对象的?
 使用hasOwnProperty( )方法检测一个属性是否存在于实例还是原型(true的是实例,false是原型);
console.log(peo1.hasOwnProperty("name"));
console.log(peo2.hasOwnProperty("name"));
这样判断严谨嘛?试试下面的代码
console.log(peo1.hasOwnProperty("name"));
console.log(peo2.hasOwnProperty("nme"));
【结论】因为这个方法判断属性不属于实例的话,就返回false,如果该实例不存在该属性它也会返回false;单从false去看,你能知道原型存在该属性嘛?不行,所以需要用到in操作符

【5】in操作符的用法: 对象名    in   对象
console.log(peo1.hasOwnProperty("name"));
console.log("name" in peo1);
console.log(peo2.hasOwnProperty("name"));
console.log("name" in peo2);
【结果】因为in操作符通过对象能够访问给定属性时返回true,不管属性是属于实例的还是属于原型的。(但是能够判断实例或者原型是否有该属性,解决了上面的问题)

封装一个方法来判断属性属于实例的还是属于原型的
/*
 * 功能:判断对象是否属于实例还是原型,true为原型
 * @object要检测的对象 @propertName对象的属性名
 * author:梦幻雪冰
 */
function prototypeProperty(object, propertName){
     return      !object.hasOwnProperty(propertName) && (propertName in object);
}

【6】如何把实例的属性删除掉? 

function Peo(name, job){
Peo.prototype.name = name;
Peo.prototype.job = job;
Peo.prototype.say = function(){
console.log("我的名字:" + this.name + " " + "我的工作:" + this.job);
}
}

var peo1 = new Peo("xiaoxiao", "前端开发");
var peo2 = new Peo("xiao", "美工");
peo1.name = "lili";
delete peo1.name;
console.log(peo1.hasOwnProperty("name"));
console.log(peo2.hasOwnProperty("name"));
console.log(peo1.name);
console.log(peo2.name);

【结论】使用delete操作则可以完全删除实例属性,则实例就不存在了name属性。

【7】上面基本实现了原型模式,但是每次增加一个原型的属性,都要写prototype,感觉比较麻烦,作为懒惰的程序开发者,来一个比较简单的写法
function Peo(){
}

Peo.prototype = {
     name : "menghuan",
     job : "teacher",
     say : function(){
          console.log(this.name);
     }
}

var peo1 = new Peo();
var peo2 = new Peo();
peo1.say();
peo2.say();
// 对象类型变成了Object 了
console.log(peo1.constructor == Peo);
console.log(peo2.constructor == Object);
【输出】
menghuan
menghuan
false 
true 
【结论】通过检测发现对象的类型不是Peo,而是变成了Object,为什么会这样呢?在JavaScript里面创建一个函数的同时也会创建prototype对象,该对象含有constructor属性,相当于重写了prototype对象,因此constructor属性也就变成了新对象的constructor属性(指向Object构造函数);这样的写法就是创建对象的写法,那么该对象的构造函数是Object(constructor指向Object),所以改变了Peo中原型对象的constructor的指向。

修改代码如下
function Peo(){
}

Peo.prototype = {
     constructor: Peo,
     name : "menghuan",
     job : "teacher",
     say : function(){
          console.log(this.name);
     }
}

var peo1 = new Peo();
var peo2 = new Peo();
peo1.say();
peo2.say();
console.log(peo1.constructor == Peo);
console.log(peo2.constructor == Peo);
console.log(peo2.constructor == Object);
【输出】
menghuan
menghuan
true
true 
false 

【8】原型的动态性:原型对象所做的任何修改都能被已经实例化的对象中访问(先创建实例再访问原型)
function Peo(){
}

Peo.prototype = {
     constructor: Peo,
     name : "menghuan",
     job : "teacher",
     say : function(){
          console.log(this.name);
     }
}

// 先创建实例
var peo1 = new Peo();
var peo2 = new Peo();
Peo.prototype.firends = ["mengmeng", "dudu"];
// 利用上面创建的实例调用刚刚动态添加的属性
console.log(peo1.firends);
peo1.say();
peo2.say();
【9】都能原型对象动态的添加属性和方法了,那把整个原型对象重写了,会发生什么事情?
function Peo(){
}

var peo1 = new Peo();
var peo2 = new Peo();
peo1.say();

Peo.prototype = {
     constructor: Peo,
     name : "menghuan",
     job : "teacher",
     say : function(){
          console.log(this.name);
     }
}
【输出】报错
【结论】原型对象所做的任何修改都能被已经实例化的对象中访问(先创建实例再访问原型),但是现在peo1对象里没有say()方法,所以会出现报错的问题。
画图辅助理解:
重写之前的状态
JavaScript 高级开发-原型 - 梦幻雪冰 - 梦幻雪冰
重写之后的状态
 JavaScript 高级开发-原型 - 梦幻雪冰 - 梦幻雪冰
   注:一般原型模式不是单独拿来使用,而是结合构造函数
欢迎学习交流-梦幻雪冰JavaScript 高级开发-原型 - 梦幻雪冰 - 梦幻雪冰


欢迎学习交流——梦幻雪冰独行冰海@font-face中iefix的详解 - 梦幻雪冰 - 梦幻雪冰
HTML5学堂贴吧——HTML5学堂
HTML5学堂微博——HTML5学堂
  评论这张
 
阅读(178)| 评论(1)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017