javascript中,像原型,闭包这样的概念,只要我们能领悟其中的原理,一切都会显得格外清晰与明了。

原型属性(prototype):

下面我们简单定义一个函数

function her(a, b){
    return a + b;
}

在这些函数一定义就被赋予的属性中,就包括prototype属性,她的初始化是一个空对象:

typeof her.prototype  // Object

当然我们也可以自己添加该属性:

her.prototype = {};

而且我们可以赋予这个空对象一些属性和方法,这并不会对foo函数产生神马影响,以为只有her()函数被当做构造函数来使用的情况下,这些属性才起作用。

来个例子:

function her(){
  this.name = 'Anna',
  this.child = 'Jok',
  this.say = function(){
       return 'My name is' + this.name + 'My child is' + this.child;
  }
}

上面是一个简单的构造函数,我们就用构造器属性prototype属性来增加她的属性和方法,您可以这样:

her.prototype.sex = 'women';
her.prototype.height = '175cm';
her.prototype.doing = function(){
    return 'I is a' + this.sex + 'I am height is' + this.height;
}

使用原型的属性和方法:

var she = new her();
she.name;  // Anna
she.child; // Jok

如上所讲如果想用以上的属性和方法,那必须new一个上述构造函数her()的一个对象实例。

对于原型来说,最重要的一点就是理解她的‘实时性’,由于在javascript中几乎所有对象都是通过引用的方式传递的。因此我们创建出来的新对象并没有属于自己的原型副本。这也就意味着我们可以随时修改prototype的属性和方法,并且由同一构造函数创建出来所有对象的prototype都会同时改变。 (甚至还会影响到修改之前就已经创建好的对象)。

继续之前的例子:

her.prototype.eat = 'water';
she.eat; // water

哪怕she之前就被创建了,我仍然还会在这个对象中访问到eat属性。

自身属性与原型属性

上述的创建doing()方法那个示例,其实直接引用一次her.prototype也可以完成上述工作:

function her(){
  this.name = 'Anna',
  this.child = 'Jok',
  this.say = function(){
       return 'My name is' + this.name + 'My child is' + this.child;
  },
  this.sex = 'women',
  this.eat = 'water'
}
her.prototype.doing = function(){
    return 'I is a' + her.prototype.sex + 'I am height is' + her.prototype.height;
}

这样有神马不同吗?要想知道这个问题就必须深入了解原型的工作原理。

var she = new her();

当我们访问she对象的某个属性时,例如she.name时,javascript引擎会遍历该对象的所有属性,并查找出name属性,如果找到了就会直接返回,否则为undefined.

这回我们访问she.sex会发生神马呢,javascript引擎依旧会查询she的所有属性,但是这回找不到一个叫sex的属性了,接下来javascript引擎就会去查找用于创建该对象的构造函数的原型(等价于我们直接访问到she.constructor.prototype),如果在原型中找到了该属性,就立刻使用该属性。

这种方式与直接访问原型属性是一样的。每个对象都有属于自己的构造器属性,这个属性引用的就是创建该对象的构造函数,所以:

she.constructor === her; // true
she.constructor.prototype.sex; // women

现在,我们回顾一下整个过程。我们知道每个对象都有一个构造器,而原型本身也是一个对象,必然也会有自己的构造器,而这个构造器又会有自己的原型。于是这种结构会一直持续下去,并取决于原型链的长度。她们的最后一环必然是Object()内建对象,她是最高级的父及对象(始祖)。

she.toString();  // Object

利用自身属性重写原型属性

通过上述我们知道一个对象自身属性中没有找到指定的属性,前提是这个属性存在,那么她就会顺着原型链去找。但是遇到对象的自身的属性和原型属性重名怎么办呢?

答案是自身属性的优先级要高于原型属性(自己的利益至上)。

来个梨子:

function her(){
   this.name = 'Anna';
}
var she = new her();
she.name = 'Lous';
she.name;  // Lous

我们可以通过hasOwnProperty()方法来判断一个属性是自身属性还是来自于原型属性。

she.hasOwnProperty('name'); // true

如果这时候我们把自身属性删掉,那么同名的原型属性又会浮出水面:

delete she.name;  //trueshe.name // Annashe.hasOwnProtype('name') // false

当然我们可以重建这个属性:

she.name = 'Lous';
she.name; // Lous;
she.hasOwnProtype('name'); // true

如何判断一个属性到底是原型链中那个原型的属性呢?答案还是用hasOwnProperty()属性。例如我们想知道toString()这个方法来自与哪里:

she.hasOwnProperty('toString');  // false
she.constructor.hasOwnProperty('toString');  // false
she.constructor.prototype.hasOwnProperty('toString');  // false
Object.hasOwnProperty('toString');  // false
Object.prototype.hasOwnProperty('toString');  // true

呵呵(*Φ皿Φ*)!!

对象的枚举属性

如果想要获得一个对象的所有属性的列表,那么就用for-in循环吧!(for循环适合数组,for-in循环更适合对象),来个栗子:

var params = {
    name : 'Anna',
    sex : 'women'
}

var url = 'http://www.baidu.com?',
      i,
      query = [];
for(i in params){
    query.push(i + '=' + params[i]);
}
url += query.join('&');  // 'http://www.baidu.com?name=Anna&sex:women';

在这里有几个细节需要注意:

  1. 不适所有的对象属性都是可以枚举的,例如length,constructor等就不会被显示,那些会显示的属性被称为可枚举的,我们可以通过各个对象所提供的propertyIsEnumerable()方法来判断对象的某个属性是不是可枚举的。

  2. 原型链中的各个属性也会被显示出来,当然她们是被可枚举的。

来个栗子:

function her(){
    this.name = 'Anna';
    this.sex = 'women';
    this.say = function(){'My name is' + this.name;}
}
var she = new her();
she.eat = 'water';

for(var i in she){
    console.log(i + '=' + she[i]);
}

name = 'Anna'
sex = 'women'
say = function(){'My name is' + this.name;}
eat = 'water'

我们再来一次,这次输出自身属性

for(var i in she){
    if(she.hasOwnProperty(i)){
        console.log(i +'='+she[i]);
    }
}

name = 'Anna'
sex = 'women'
say = function(){'My name is' + this.name}

未完待续。。。。。。

javascript --- 原型初探七日谈(一)的更多相关文章

  1. javascript --- 原型初探七日谈(二)

    扩展内建对象: 在javascript中,内建对象的构造函数都是可以通过其原型来进行扩展的.这意味着我们可以做一些事情,例如我们要往数组原型中添加一个新方法,就可以在其所有的数组中使用,下面我们来试试 ...

  2. javascript --- 原型初探七日谈(三)

    原型陷阱: 在处理原型问题上时,我们要注意两种行为. 1. 当我们对原型对象执行完全替换的时候,有可能会触发原型链的某种异常. 2. prototype.constructor 属性是不可靠的. 下面 ...

  3. javascript --- 继承初探七日谈 (一)

    原型链是javascript实现继承的默认方式.下面来一个例子看一下她的魔法吧: 首先定义三个构造函数: function her(){ this.name = 'Anna'; this.toStri ...

  4. 浅谈系列之 javascript原型与对象

    在我学习与使用javascript三个月中,我一直对javascript的继承关系以及prototype理解不清,导致很多时候为什么这么用说不出个所以然来.截止到本周为止,通过之前的学习以及自己的再学 ...

  5. JavaScript原型OOP——你上车了吗?

    .title-bar { width: 80%; height: 35px; padding-left: 35px; color: white; line-height: 35px; font-siz ...

  6. 深入理解javascript原型和闭包 (转)

    该教程绕开了javascript的一些基本的语法知识,直接讲解javascript中最难理解的两个部分,也是和其他主流面向对象语言区别最大的两个部分--原型和闭包,当然,肯定少不了原型链和作用域链.帮 ...

  7. 深入理解javascript原型和闭包系列

    从下面目录中可以看到,本系列有16篇文章,外加两篇后补的,一共18篇文章.写了半个月,从9月17号开始写的.每篇文章更新时,读者的反馈还是可以的,虽然不至于上头条,但是也算是中规中矩,有看的人,也有评 ...

  8. 深入理解javascript原型和闭包(1)——一切都是对象

    “一切都是对象”这句话的重点在于如何去理解“对象”这个概念. ——当然,也不是所有的都是对象,值类型就不是对象. 首先咱们还是先看看javascript中一个常用的函数——typeof().typeo ...

  9. 深入理解javascript原型和闭包(2)——函数和对象的关系

    上文(理解javascript原型和作用域系列(1)——一切都是对象)已经提到,函数就是对象的一种,因为通过instanceof函数可以判断. var fn = function () { }; co ...

随机推荐

  1. 面试准备 - 最大堆的Csharp实现

    面试中最常见的问题之一...在N个数中间寻找前K大个元素 最常见的解法就是最大堆 时间复杂度O(N*log(K)) 空间复杂度O(k) 实现了一个最简单的最大堆,每次有元素进来都和堆顶元素比较一下,如 ...

  2. 《HelloGitHub月刊》第04期(秋招临近,本期加入了面试相关的项目)

    兴趣是最好的老师,而<HelloGitHub> 就是帮你找到兴趣! 因为我比较熟悉python语言,所以月刊中python语言的项目居多,个人能力有限,其他语言涉及甚少,欢迎各路人士加入, ...

  3. MFC抓网页

    CString chinachar_str("读取的东西:"); CInternetSession sion(NULL,); CHttpFile *http=NULL; CStri ...

  4. postgres中的中文分词zhparser

    postgres中的中文分词zhparser postgres中的中文分词方法 基本查了下网络,postgres的中文分词大概有两种方法: Bamboo zhparser 其中的Bamboo安装和使用 ...

  5. 基于HTML5的Drag and Drop生成图片Base64信息

    HTML5的Drag and Drop是很不错的功能,网上使用例子较多如 http://html5demos.com/drag ,但这些例子大部分没实际用途,本文将搞个有点使用价值的例子,通过Drag ...

  6. Moon.Orm 5.0(MQL版)分页功能的设计(求指教,邀请您的加入)

    一.分页的分类及分析 1)分页的前置条件: 查询的目标条件.第几页.总页数(本质上由查询条件决定).每页条数.请求地址.按照什么字段怎样排序 2)目标结果: 数据列表,List<T>返回 ...

  7. 原生js实现简洁的返回顶部组件

    本文内容相当简单,所以没有发布到博客园首页,如果你不幸看到,那只能是我这篇文章的荣幸,谢谢你的大驾光临~(本博客返回顶部的功能就使用的是这个组件) 返回顶部组件是一种极其常见的网页功能,需求简单:页面 ...

  8. 使用GitHub for Windows客户端管理京东代码库项目

    1.下载并安装 GitHub for Windows 客户端 https://windows.github.com/ 2.在京东代码库中新的代码库,可以创建私有的代码库 https://code.jd ...

  9. C#编程总结(一)序列化

    C#编程总结(一)序列化 序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数据. 几种序列化技术:      1) ...

  10. C# 通过GPS坐标,计算两点之间距离

    之前在网上有很多这种计算的,但是代码都不怎么全.经过多方打听查询.找到完整代码.现将代码共享给大家. 有需要者觉得有用者欢迎使用.觉得用或简单的高手,请绕. public static double ...