当前位置:千赢国际官网 > 千赢网页手机版登入 > 创建对象的,数组和对象就像书和报纸一样

创建对象的,数组和对象就像书和报纸一样

文章作者:千赢网页手机版登入 上传时间:2019-11-23

JavaScript 数组和对象就像书和报纸一样

2017/05/26 · JavaScript · 对象, 数组

原文出处: Kevin Kononenko   译文出处:蔡耀冠   

简评:作者将 JavaScript 的数组和对象比喻为书和报纸,数组更注重顺序,而标签则对对象更重要。

如果你读书、看报,那么你会理解 JavaScript 的数组和对象之间的不同之处。

当你刚开始学 JavaScript 时,用哪一种方式组织和存储数据更好往往会让人困惑。

一方面,你可能在学习 “for” 循环的时候熟悉了数组。但是,一旦你尽可能多地将数据塞进数组,当你在检查你的代码的时候,你创造的乱七八糟的东西将会让你难以理解。

当你可以快速地决定每个结构的目标时,在对象和数组之间选择会简单得多。数组和书籍存储信息的方式相差无几,而对象则和报纸存储信息的方式差不多。

让我们来看看!

JS原生Date类型方法的一些冷知识

2015/09/07 · JavaScript · Date

原文出处: chitanda   

一个多月没更新了- -偷懒中。这个东西其实很早之前就在整理了,不过后来发现自己不少地方没弄明白,然后就一直卡那边了(其实就是不想写吧),想了下反正是给自己熟悉js的原生API而已,所以也没必要太钻牛角尖,也不一定要多完整,因此就当是Date()函数的一个冷门知识点小补充吧。这篇文章主要讲Date()的字符串与时间戳转换以及用户时间本地化,可能内容上比较乱(不然也不会卡我一个月时间了),见谅

ps:由于 Date() 是js原生函数,不同浏览器的解析器对其实现方式并不同,所以返回值也会有所区别。本文测试未特别申明浏览器的情况下,均是指 win7 x64 chrome 44.0.2403.155 (正式版本) m (32 位) 版本

浅谈 JS 创建对象的 8 种模式

2015/10/16 · JavaScript · 对象

原文出处: Tomson   

  • Objct 模式
  • 工厂模式
  • 构造器模式
  • 通过 Function 对象实现
  • prototype 模式
  • 构造器与原型方式的混合模式
  • 动态原型模式
  • 混合工厂模式

数组:数据的顺序是最重要的

这是超短篇小说的章节,以数组的形式。

JavaScript

var book = ['foreword', 'boyWhoLived', 'vanishingGlass', 'lettersFromNoOne', 'afterword'];

1
var book = ['foreword', 'boyWhoLived', 'vanishingGlass', 'lettersFromNoOne', 'afterword'];

好吧,我承认,这是《哈利波特》系列的第一本的前三章。这是数组的可视化的形式:

图片 1当顺序成为组织信息的最重要的因素时你应该使用数组。没有人(我希望)这样看《哈利波特》的章节标题,“嗯…,那章看起来很有趣,让我跳到那!”章节的顺序告诉你下一章是什么。

当你从数组中检索信息时,你使用每个元素的下标。数组是从零开始索引的,这意味着从 0 开始计数而不是 1。

如果你想要访问下标为 0 的书籍数组,你要用:

JavaScript

books[0]

1
books[0]

然后你会得到:

JavaScript

'foreword'

1
'foreword'

如果你想得到这本书第三章的章节标题,你要用:

JavaScript

books[2]

1
books[2]

你会基于书的章节顺序来读下一章,而不是基于书的章节标题。

Date()与new Date()的区别

Date() 直接返回当前时间字符串,不管参数是number还是任何string

JavaScript

Date(); Date('sssss'); Date(1000); //Fri Aug 21 2015 15:46:21 GMT 0800 (中国标准时间)

1
2
3
4
Date();
Date('sssss');
Date(1000);
//Fri Aug 21 2015 15:46:21 GMT 0800 (中国标准时间)

而 new Date() 则是会根据参数来返回对应的值,无参数的时候,返回当前时间的字符串形式;有参数的时候返回参数所对应时间的字符串。 new Date() 对参数不管是格式还是内容都要求,且只返回字符串,

JavaScript

new Date(); //Fri Aug 21 2015 15:51:55 GMT 0800 (中国标准时间) new Date(1293879600000); new Date('2011-01-01T11:00:00') new Date('2011/01/01 11:00:00') new Date(2011,0,1,11,0,0) new Date('jan 01 2011,11 11:00:00') new Date('Sat Jan 01 2011 11:00:00') //Sat Jan 01 2011 11:00:00 GMT 0800 (中国标准时间) new Date('sss'); new Date('2011/01/01T11:00:00'); new Date('2011-01-01-11:00:00') new Date('1293879600000'); //Invalid Date new Date('2011-01-01T11:00:00')-new Date('1992/02/11 12:00:12') //596069988000

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
new Date();
//Fri Aug 21 2015 15:51:55 GMT 0800 (中国标准时间)
 
new Date(1293879600000);
new Date('2011-01-01T11:00:00')
new Date('2011/01/01 11:00:00')
new Date(2011,0,1,11,0,0)
new Date('jan 01 2011,11 11:00:00')
new Date('Sat Jan 01 2011 11:00:00')
//Sat Jan 01 2011 11:00:00 GMT 0800 (中国标准时间)
 
new Date('sss');
new Date('2011/01/01T11:00:00');
new Date('2011-01-01-11:00:00')
new Date('1293879600000');
//Invalid Date
 
new Date('2011-01-01T11:00:00')-new Date('1992/02/11 12:00:12')
//596069988000

从上面几个测试结果可以很容易发现

  1. new Date() 在参数正常的情况只会返回当前时间的字符串(且是当前时区的时间)
  2. new Date() 在解析一个具体的时间的时候,对参数有较严格的格式要求,格式不正确的时候会直接返回Invalid Date,比如将 number 类的时间戳转换成 string 类的时候也会导致解析出错
  3. 虽然 new Date() 的返回值是字符串,然而两个 new Date() 的结果字符串是可以直接相减的,结果为相差的毫秒数。

那么, new Date() 能接受的参数格式到底是什么标准呢?(相对于严格要求的多参数传值方法。非严格的单参数(数字日期表示格式)更常用且更容易出错,所以下文只考虑单参数数字时间字符串转换的情况)

表示格式)更常用且更容易出错,所以下文只考虑单参数数字时间字符串转换的情况)


1.Object 模式

JavaScript

var o1 = {};//字面量的表现形式 var o2 = new Object; var o3 = new Object(); var o4 = new Object(null); var o5 = new Object(undefined); var o6 = Object.create(Object.prototype);//等价于 var o = {};//即以 Object.prototype 对象为一个原型模板,新建一个以这个原型模板为原型的对象 //区别 var o7 = Object.create(null);//创建一个原型为 null 的对象

1
2
3
4
5
6
7
8
var o1 = {};//字面量的表现形式
var o2 = new Object;
var o3 = new Object();
var o4 = new Object(null);
var o5 = new Object(undefined);
var o6 = Object.create(Object.prototype);//等价于 var o = {};//即以 Object.prototype 对象为一个原型模板,新建一个以这个原型模板为原型的对象
//区别
var o7 = Object.create(null);//创建一个原型为 null 的对象

在 chrome 里查看各个新建对象的区别:
图片 2

可以看出前6种模式创建出来的对象都是一样的,第七种不同点在于其虽然也为 Object 对象但其无任何属性(包括没有任何可以继承的属性,因为创建的时候没有指定其原型)

对象:数据标签是最重要的

报纸可能看起来是这样的,以对象的形式。

JavaScript

var newspaper= { sports: 'ARod Hits Home Run', business: 'GE Stock Dips Again', movies: 'Superman Is A Flop' }

1
2
3
4
5
var newspaper= {
  sports: 'ARod Hits Home Run',
  business: 'GE Stock Dips Again',
  movies: 'Superman Is A Flop'
}

下面是以可视化的形式来看同样的数据。

图片 3当你要基于数据标签来组织数据时,对象是最好的。当你看报纸时,你可能不会从前往后一页页地读。你会基于新闻标题来跳过特定的部分。无论在报纸的哪个地方,你都可以快速的跳过并且有合适的上下文。这和书不一样,书的章节顺序很重要。

对象通过键/值对来组织数据。看起来像这样:

JavaScript

key: value

1
key: value

如果你想要进入报纸的商业部分,你会使用这样的

JavaScript

newspaper[‘business’]

1
newspaper[‘business’]

或者:

JavaScript

newspaper.business

1
newspaper.business

这回返回 ‘GE Stock Dips Again’。所以,通过数据的标签(键)来访问数据是最简单的,你想要把数据存在对象里。

new Date()解析所支持的参数格式标准

2.工厂模式

JavaScript

//工厂方法1 通过一个方法来创建对象 利用 arguments 对象获取参数设置属性(参数不直观,容易出现问题) function createCar(){ var oTemp = new Object(); oTemp.name = arguments[0];//直接给对象添加属性,每个对象都有直接的属性 oTemp.age = arguments[1]; oTemp.showName = function () { alert(this.name); };//每个对象都有一个 showName 方法版本 return oTemp; } createCar("tom").showName();//在 JS 中没有传递的实参,实际形参值为 undefined(这里的 age 为 undefined) createCar("tim",80).showName(); alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类

1
2
3
4
5
6
7
8
9
10
11
12
13
//工厂方法1 通过一个方法来创建对象 利用 arguments 对象获取参数设置属性(参数不直观,容易出现问题)
function createCar(){
    var oTemp = new Object();
    oTemp.name = arguments[0];//直接给对象添加属性,每个对象都有直接的属性
    oTemp.age = arguments[1];
    oTemp.showName = function () {
        alert(this.name);
    };//每个对象都有一个 showName 方法版本
    return oTemp;
}
createCar("tom").showName();//在 JS 中没有传递的实参,实际形参值为 undefined(这里的 age 为 undefined)
createCar("tim",80).showName();
alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类

JavaScript

//工厂方法2 通过传参设置属性(参数直观明了) function createCar(name,age){ var oTemp = new Object(); oTemp.name = name;//直接给对象添加属性,每个对象都有直接的属性 oTemp.age = age; oTemp.showName = function () { alert(this.name); };//每个对象都有一个 showName 方法版本 return oTemp; } createCar("tom").showName(); createCar("tim",80).showName(); alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类

1
2
3
4
5
6
7
8
9
10
11
12
13
//工厂方法2 通过传参设置属性(参数直观明了)
function createCar(name,age){
    var oTemp = new Object();
    oTemp.name = name;//直接给对象添加属性,每个对象都有直接的属性
    oTemp.age = age;
    oTemp.showName = function () {
        alert(this.name);
    };//每个对象都有一个 showName 方法版本
    return oTemp;
}
createCar("tom").showName();
createCar("tim",80).showName();
alert(createCar("tom") instanceof Object);//true 判断对象是否 Object 类或子类

结合对象和数组

目前为止,我们只是在数组和对象中保存了 strings,你也可以保存其他类型的数据,比如 numbers 和 booleans,同时:

  1. 对象内的数组
  2. 数组中的对象
  3. 数组中的数组
  4. 对象中的对象

现在开始变复杂了。但是,你几乎只需要两种以扩展方式的组合来存储你的数据。当你一星期后回顾代码也想要理解。

让我们再看下书的例子。如果我们想要保存每章的页数会怎样呢?用对象来填满我们的数组可能是最好的。像这样:

JavaScript

var book =[ [‘foreword’, 14], [‘boywholived’, 18] ]

1
2
3
4
var book =[
  [‘foreword’, 14],
  [‘boywholived’, 18]
]

JavaScript

var book = [ {name:'foreword', pageCount: 14}, {name:'boyWhoLived', pageCount: 18}, {name:'vanishingGlass', pageCount: 13}, {name:'lettersFromNoOne', pageCount: 17}, {name:'afterword', pageCount: 19} ];

1
2
3
4
5
6
7
var book = [
  {name:'foreword', pageCount: 14},
  {name:'boyWhoLived', pageCount: 18},
  {name:'vanishingGlass', pageCount: 13},
  {name:'lettersFromNoOne', pageCount: 17},
  {name:'afterword', pageCount: 19}
];

我们维护了每章的顺序,现在我们可以叫出每章的特定的属性。所以,如果我们想要知道第二张的页数,我们可以用:

JavaScript

book[1][‘pageCount’]

1
book[1][‘pageCount’]

这会返回一个 18 的

现在假设你想知道你当地报纸每个栏目的顶级作者的排名,基于他们的资历。你可以在报纸对象中用一个数组来表达,像这样:

JavaScript

var newspaper= { sports: 'ARod Hits Home Run', sportsWriters: ['Miramon Nuevo', 'Rick Reilly', 'Woddy Paige'], business: 'GE Stock Dips Again', businessWriters: ['Adam Smith', 'Albert Humphrey', 'Charles Handy'], movies: 'Superman Is A Flop', moviesWriters: ['Rogert Ebert', 'Andrew Sarris', 'Wesley Morris'] }

1
2
3
4
5
6
7
8
var newspaper= {
  sports: 'ARod Hits Home Run',
  sportsWriters: ['Miramon Nuevo', 'Rick Reilly', 'Woddy Paige'],
  business: 'GE Stock Dips Again',
  businessWriters: ['Adam Smith', 'Albert Humphrey', 'Charles Handy'],
  movies: 'Superman Is A Flop',
  moviesWriters: ['Rogert Ebert', 'Andrew Sarris', 'Wesley Morris']
}

一个数组用来存储作者很合适,因为顺序很重要。你知道每个数组中靠前的作者排名更高。下标为 0 的作者是排名最高的。

你可以通过创建对象来优化报纸对象。比如,一个包含标题和作者列表的体育对象。但我会让你来尝试!

1 赞 2 收藏 评论

图片 4

时间戳格式

这个是最简单的也是最不容易出错的。当然唯一的缺点大概就是对开发者不直观,无法一眼看出具体日期。
需要注意的以下两点:

  1. js内的时间戳指的是当前时间到1970年1月1日00:00:00 UTC对应的毫秒数,和unix时间戳不是一个概念,后者表示秒数,差了1000倍
  2. class="crayon-syntax crayon-syntax-inline crayon-theme-github crayon-theme-github-inline crayon-font-monaco" style="font-size: 13px !important; line-height: 15px !important;font-size: 13px !important;"> class="crayon-pre crayon-code" style="font-size: 13px !important; line-height: 15px !important;font-size: 13px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;"> class="crayon-r">new class="crayon-r">Date( class="crayon-v">timestamp class="crayon-sy">) 中的时间戳必须是number格式, class="crayon-syntax crayon-syntax-inline crayon-theme-github crayon-theme-github-inline crayon-font-monaco" style="font-size: 13px !important; line-height: 15px !important;font-size: 13px !important;"> class="crayon-pre crayon-code" style="font-size: 13px !important; line-height: 15px !important;font-size: 13px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;"> class="crayon-t">string 会返回Invalid Date。所以比如new Date('11111111')这种写法是错的

3.构造器模式

JavaScript

//构造器方法1 function Car(sColor,iDoors){ //声明为构造器时需要将函数名首字母大写 this.color = sColor; //构造器内直接声明属性 this.doors = iDoors; this.showColor = function(){ return this.color; };//每个 Car 对象都有自己的 showColor方法版本 this.showDoor = function () { return this.doors; } }

1
2
3
4
5
6
7
8
9
10
11
//构造器方法1
function Car(sColor,iDoors){  //声明为构造器时需要将函数名首字母大写
    this.color = sColor;      //构造器内直接声明属性
    this.doors = iDoors;
    this.showColor = function(){
        return this.color;
    };//每个 Car 对象都有自己的 showColor方法版本
    this.showDoor = function () {
        return this.doors;
    }
}

使用方法1的问题很明显,没办法是 showDoor 方法重用,每次新建一个对象就要在堆里新开辟一篇空间.改进如下

JavaScript

//构造器方法2 function showDoor(){ //定义一个全局的 Function 对象 return this.doors; } function Car(sColor,iDoors){//构造器 this.color = sColor; //构造器内直接声明属性 this.doors = iDoors; this.showColor = function(){ return this.color; }; this.showDoor = showDoor();//每个 Car 对象共享同一个 showDoor 方法版本(方法有自己的作用域,不用担心变量被共享) } alert(new Car("red",2).showColor());//通过构造器创建一个对象并调用其对象方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//构造器方法2
function showDoor(){      //定义一个全局的 Function 对象
    return this.doors;
}
 
function Car(sColor,iDoors){//构造器
    this.color = sColor;      //构造器内直接声明属性
    this.doors = iDoors;
    this.showColor = function(){
        return this.color;
    };
    this.showDoor = showDoor();//每个 Car 对象共享同一个 showDoor 方法版本(方法有自己的作用域,不用担心变量被共享)
}
 
alert(new Car("red",2).showColor());//通过构造器创建一个对象并调用其对象方法

上面出现的问题就是语义不够清除,体现不出类的封装性,改进为 prototype 模式

时间数字字符串格式

不大清楚这种该怎么描述,就是类似YYYY/MM/DD HH:mm:SS这种。下文以dateString代指。
new Date(dateString)所支持的字符串格式需要满足RFC2822标准或者ISO 8601标准
这两种标准对应的格式分别如下:

  1. RFC2822 标准日期字符串
JavaScript

YYYY/MM/DD HH:MM:SS ± timezon(时区用4位数字表示) // eg 1992/02/12
12:23:22 0800

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6c187675a314957670-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6c187675a314957670-2">
2
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6c187675a314957670-1" class="crayon-line">
YYYY/MM/DD HH:MM:SS ± timezon(时区用4位数字表示)
</div>
<div id="crayon-5b8f6c187675a314957670-2" class="crayon-line crayon-striped-line">
// eg 1992/02/12 12:23:22 0800
</div>
</div></td>
</tr>
</tbody>
</table>

>  RFC2822还有别的格式,不过上面这个是比较常用的(另外这标准太难啃了,实在没耐心啃完,所以也就没太深入)。RFC2822标准本身还有其他的非数字日期表达方式,不过不在这个话题讨论范围内了,略过
  1. ISO 8601标准日期字符串
JavaScript

YYYY-MM-DDThh:mm:ss ± timezone(时区用HH:MM表示) 1997-07-16T08:20:30Z
//
“Z”表示UTC标准时区,即"00:00",所以这里表示零时区的`1997年7月16日08时20分30秒`
//转换成位于东八区的北京时间则为`1997年7月17日16时20分30秒`
1997-07-16T19:20:30 01:00 //
表示东一区的1997年7月16日19时20秒30分,转换成UTC标准时间的话是1997-07-16T18:20:30Z

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6c187675d765819674-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6c187675d765819674-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6c187675d765819674-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6c187675d765819674-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6c187675d765819674-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6c187675d765819674-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f6c187675d765819674-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6c187675d765819674-8">
8
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6c187675d765819674-1" class="crayon-line">
 YYYY-MM-DDThh:mm:ss ± timezone(时区用HH:MM表示)
</div>
<div id="crayon-5b8f6c187675d765819674-2" class="crayon-line crayon-striped-line">
 
</div>
<div id="crayon-5b8f6c187675d765819674-3" class="crayon-line">
 1997-07-16T08:20:30Z
</div>
<div id="crayon-5b8f6c187675d765819674-4" class="crayon-line crayon-striped-line">
 // “Z”表示UTC标准时区,即&quot;00:00&quot;,所以这里表示零时区的`1997年7月16日08时20分30秒`
</div>
<div id="crayon-5b8f6c187675d765819674-5" class="crayon-line">
 //转换成位于东八区的北京时间则为`1997年7月17日16时20分30秒`
</div>
<div id="crayon-5b8f6c187675d765819674-6" class="crayon-line crayon-striped-line">
 
</div>
<div id="crayon-5b8f6c187675d765819674-7" class="crayon-line">
 1997-07-16T19:20:30 01:00
</div>
<div id="crayon-5b8f6c187675d765819674-8" class="crayon-line crayon-striped-line">
 // 表示东一区的1997年7月16日19时20秒30分,转换成UTC标准时间的话是1997-07-16T18:20:30Z
</div>
</div></td>
</tr>
</tbody>
</table>
  1. 日期和时间中间的T不可以被省略,一省略就出错。
  2. 虽然在chrome浏览器上时区也可以用 0100这种RFC2822的形式来表示,然而IE上不支持这种混搭写法,所以用ISO8601标准形式表示的时候时区要用 HH:MM

单单从格式上来说,两者的区别主要在于分隔符的不同。不过需要注意的是,ISO 8601标准的兼容性比RFC2822差得多(比如IE8和iOS均不支持前者。我知道IE8很多人会无视,不过iOS也有这个坑的话,各位或多或少会谨慎点了吧?),所以一般情况下建议用RFC 2822格式的。
不过需要注意的是,在未指定时区的前提下,对于只精确到day的日期字符串,RFC 2822返回结果是以当前时区的零点为准,而ISO8601返回结果则会以UTC时间的零点为标准进行解析。
例如:

JavaScript

//RFC2822: new Date('1992/02/13') //Thu Feb 13 1992 00:00:00 GMT 0800 (中国标准时间) //ISO8601: new Date('1992-02-13') //Thu Feb 13 1992 08:00:00 GMT 0800 (中国标准时间)

1
2
3
4
//RFC2822:
new Date('1992/02/13') //Thu Feb 13 1992 00:00:00 GMT 0800 (中国标准时间)
//ISO8601:
new Date('1992-02-13') //Thu Feb 13 1992 08:00:00 GMT 0800 (中国标准时间)

 

然而上面这个只是ES5的标准而已,在ES6里这两种形式都会变成当前时区的零点为基准1
*不管你们崩溃没,反正我是已经想死了*
关于跨浏览器的dataString解析情况,还可以参考这个页面:
JavaScript and Dates, What a Mess!

所以对于时间字符串对象,个人意见是要么用RFC2822形式,要么自己写个解析函数然后随便你传啥格式进来。


4.通过Function对象实现创建对象

我们知道每声明一个函数实际是创建了一个Function 实例 JS 函数.

JavaScript

function function_name(param1,param2){alert(param1);} //等价于 var function_name = new Function("param1","pram2","alert(param1);");

1
2
3
function function_name(param1,param2){alert(param1);}
//等价于
var function_name = new Function("param1","pram2","alert(param1);");

JavaScript

var Car2 = new Function("sColor","iDoors", "this.color = sColor;" "this.doors = iDoors;" "this.showColor = function(){ return this.color; }" ); alert(new Car2("blue",3).showColor());

1
2
3
4
5
6
var Car2 = new Function("sColor","iDoors",
         "this.color = sColor;"
         "this.doors = iDoors;"
         "this.showColor = function(){ return this.color; }"
);
alert(new Car2("blue",3).showColor());

时间格式化函数的效率

这里的时间格式化值得是将时间字符串转换成毫秒数的过程。js原生的时间格式化函数有Date.parseDate.prototype.valueOfDate.prototype.getTimeNumber(Date) Date(还有个Date.UTC方法,然而对参数要求严格,不能直接解析日期字符串,所以略过)
这5个函数从功能上来说一模一样,但是具体的效率如何呢?我写了个检测页面,诸位也可以自己测试下。
点击预览

5.prototype模式

  • 类通过 prototype 属性添加的属性与方法都是绑定在这个类的 prototype 域(实际为一个 Prototype 对象)中,绑定到这个域中的属性与方法只有一个版本,只会创建一次.
  • 类的实例对象可以直接像调用自己的属性一样调用该类的 prototype 域中的属性与方法,类可以通过调用 prototype 属性来间接调用prototype 域内的属性与方法.

注意:通过类实例化出对象后对象内无 prototype 属性,但对象可直接像访问属性一样的访问类的 prototype 域的内容,实例对象有个私有属性__proto__,__proto__属性内含有类的 prototype 域内的属性与方法

JavaScript

方法1 function Car3(){}//用空构造函数设置类名 Car3.prototype.color = "blue";//每个对象都共享相同属性 Car3.prototype.doors = 3; Car3.prototype.drivers = new Array("Mike","John"); Car3.prototype.showColor = function(){ alert(this.color); };//每个对象共享一个方法版本,省内存。 var car3_1 = new Car3(); var car3_2 = new Car3(); alert(car3_1.color);//blue alert(car3_2.color);//blue alert(Car3.prototype.color);//blue car3_1.drivers.push("Bill"); alert(car3_1.drivers);//"Mike","John","Bill" alert(car3_2.drivers);//"Mike","John","Bill" alert(Car3.prototype.drivers);//"Mike","John","Bill" //直接修改实例对象的属性,解析器会先去找实例对象是否有这个属性(不会去找实例对象的 _proto_ 属性内的那些类的 prototype 属性,而是直接查看这个实例是否有对应的属性(与_proto_同级)) //如果没有则直接给这个实例对象添加该属性,但不会修改类的prototype域的同名属性,既实例对象的_proto_属性内的那些类 prototype 域属性不会被修改 car3_1.color = "red";//car3_1对象内无名为 color 的对象属性,故将该属性添加到该对象上 //解析器对实例对象读取属性值的时候会先查找该实例有无同名的直接属性 //如果没有,则查找__proto__属性内保存的那些 当前类的 prototype 域的属性 //有就返回,无则继续查找是否有原型链中的对应的方法属性 //有就返回,无则返回undefined alert(car3_1.color);//red alert(car3_2.color);//blue alert(car3_2.color2);//undefined //直接修改类的 prototype 域内的属性,不会影响该类的实例对象的对象属性,但会影响实例对象的_proto_属性(_proto_属性内存放的是类的 prototype 域的内容) Car3.prototype.color = "black"; alert(car3_1.color);//red 该对象有同名的直接属性,故不会去_proto_属性内查找类的 prototype 域的属性 alert(car3_2.color);//black 受影响 //直接修改实例对象的方法,解析器会先去找实例对象是否有这个方法(不会去找实例对象的 _proto_ 属性内的那些类的 prototype 域的方法,而是直接查看这个实例是否有对应的方法(与_proto_同级)) //如果没有则直接给这个实例对象添加该方法,但不会修改类的prototype域的同名方法,既实例对象的_proto_属性内的那些类 prototype 域方法不会被修改 //car3_1对象内无名为 showColor 的对象方法属性,故将该方法属性添加到该对象上 car3_1.showColor = function () { alert("new function"); } //解析器对实例对象调用方法属性的时候会先查找该实例有无同名的直接方法属性 //如果没有,则查找_proto_属性内保存的那些 当前类的 prototype 域的方法属性 //有就返回,无则继续查找是否有原型链中的对应的方法属性 //找到就返回,无则报错 car3_1.showColor();//new function car3_2.showColor();//blue car3_1.abcd();//直接报错 //直接修改类的 prototype 域内的方法属性,不会影响该类的实例对象的方法属性,但会影响实例对象的_proto_属性(_proto_属性内存放的是类的 prototype 域的内容) Car3.prototype.showColor = function () { alert("second function"); } car3_1.showColor();//new function 该对象有同名的方法属性,故不会去_proto_属性内查找类的 prototype 域的方法属性 car3_2.showColor();//second function 受影响

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
方法1
function Car3(){}//用空构造函数设置类名
Car3.prototype.color = "blue";//每个对象都共享相同属性
Car3.prototype.doors = 3;
Car3.prototype.drivers = new Array("Mike","John");
Car3.prototype.showColor = function(){
    alert(this.color);
};//每个对象共享一个方法版本,省内存。
 
var car3_1 = new Car3();
var car3_2 = new Car3();
 
alert(car3_1.color);//blue
alert(car3_2.color);//blue
alert(Car3.prototype.color);//blue
 
car3_1.drivers.push("Bill");
alert(car3_1.drivers);//"Mike","John","Bill"
alert(car3_2.drivers);//"Mike","John","Bill"
alert(Car3.prototype.drivers);//"Mike","John","Bill"
 
//直接修改实例对象的属性,解析器会先去找实例对象是否有这个属性(不会去找实例对象的 _proto_ 属性内的那些类的 prototype 属性,而是直接查看这个实例是否有对应的属性(与_proto_同级))
//如果没有则直接给这个实例对象添加该属性,但不会修改类的prototype域的同名属性,既实例对象的_proto_属性内的那些类 prototype 域属性不会被修改
car3_1.color = "red";//car3_1对象内无名为 color 的对象属性,故将该属性添加到该对象上
 
//解析器对实例对象读取属性值的时候会先查找该实例有无同名的直接属性
//如果没有,则查找__proto__属性内保存的那些 当前类的 prototype 域的属性
//有就返回,无则继续查找是否有原型链中的对应的方法属性
//有就返回,无则返回undefined
alert(car3_1.color);//red
alert(car3_2.color);//blue
alert(car3_2.color2);//undefined
 
//直接修改类的 prototype 域内的属性,不会影响该类的实例对象的对象属性,但会影响实例对象的_proto_属性(_proto_属性内存放的是类的 prototype 域的内容)
Car3.prototype.color = "black";
alert(car3_1.color);//red 该对象有同名的直接属性,故不会去_proto_属性内查找类的 prototype 域的属性
alert(car3_2.color);//black 受影响
 
//直接修改实例对象的方法,解析器会先去找实例对象是否有这个方法(不会去找实例对象的 _proto_ 属性内的那些类的 prototype 域的方法,而是直接查看这个实例是否有对应的方法(与_proto_同级))
//如果没有则直接给这个实例对象添加该方法,但不会修改类的prototype域的同名方法,既实例对象的_proto_属性内的那些类 prototype 域方法不会被修改
//car3_1对象内无名为 showColor 的对象方法属性,故将该方法属性添加到该对象上
car3_1.showColor = function () {
    alert("new function");
}
//解析器对实例对象调用方法属性的时候会先查找该实例有无同名的直接方法属性
//如果没有,则查找_proto_属性内保存的那些 当前类的 prototype 域的方法属性
//有就返回,无则继续查找是否有原型链中的对应的方法属性
//找到就返回,无则报错
 
car3_1.showColor();//new function
car3_2.showColor();//blue
car3_1.abcd();//直接报错
 
//直接修改类的 prototype 域内的方法属性,不会影响该类的实例对象的方法属性,但会影响实例对象的_proto_属性(_proto_属性内存放的是类的 prototype 域的内容)
Car3.prototype.showColor = function () {
    alert("second function");
}
car3_1.showColor();//new function 该对象有同名的方法属性,故不会去_proto_属性内查找类的 prototype 域的方法属性
car3_2.showColor();//second function 受影响

可以看出使用该方法虽然说打打减少了内存的浪费,但依旧有问题,某个对象的属性一旦改变,所有由该类实例化得到的对象的__proto__内属性值也会跟着变(实为引用),改进如下

本文由千赢国际官网发布于千赢网页手机版登入,转载请注明出处:创建对象的,数组和对象就像书和报纸一样

关键词: 千赢国际官网