本文主要总结了javascript 常用功能总结,如一些常用的额js 对象,基本数据结构,功能函数等,还有一些常用的设计模式。
目录:
众所周知,javascript是动态的面向对象的编程语言,能够实现以下效果:
丰富web 网页功能 丰富web界面 实现本地或远程存储。 实现分布式网络应用的前端组件,并在后台进行数据存储管理。 使用javascript可以实现完整的分布式web 应用。 一、javascript 中的数据类型
javascript 提供三种元数据类型,string,number,和boolean,可使用typeof(v) 测试变量v 的类型,typeof(v)===number
提供五种基本的引用类型:object, array, function, date 及regexp。数组,函数,日期和正则表达式是特殊类型,但是严格来讲,日期和正则表达式是元数据类型,可封装在其他对象中。
js 中变量类型,数组元素类型,函数参数以及返回值的类型不需要声明类型,类型之间的转换是自动执行的。
变量值可以是:
1. 数值:如字符串,数字或布尔值。 2. 对象引用: 可引用典型对象,也可以是数据,函数,日期或正则表达式。 3. 特殊数据值,null,是典型的用于初始化对象的默认值。 4. 特殊数据undefined,常用于已被定义,但未赋值的变量。string 是一系列的unicode 字符串,string 如“hello world”,'a3fo'或空字符串“”,字符串连接可通过+操作符来执行,也可以使用=号来验证两个字符串是否相等;
if (firstname + lastname === james bond) ...
numeric 表示64位的浮点数,在js 中没有明显的区分整形和浮点数,如果一个表达式的值不等于某个数字,那么它的值可设为nan,表示非数字,可联合isnan使用。
如下表是详细的类型测试和转换
二、变量作用域范围
目前,javascript,es5提供两种作用域类型:全局变量及函数作用域,没有块作用域。块作用域的范围不太明确,所以应当避免块作用域的使用。如下代码,尽管是开发人员常用的pattern,却是一个陷阱。
function foo() { for (var i=0; i < 10; i++) { ... // do something with i }}
所有的变量声明最好是在函数的开始位置。在js,es6版本中支持块作用域,采用关键字let 定义变量。
严格模式(strict mode)
从es5开始, 严格模式用于检测运行时的错误,在严格模式下,所有的变量必须声明,如果给未声明的变量赋值会抛出异常。
在javascript 文件或元素内,通过输入以下代码切换到严格模式:
use strict;
建议采用严格模式,除非项目依赖的库不兼容严格模式。
多种对象
js中的对象概念不同于oo或uml中的对象,尤其是在js中对象不需要实例化,也可以有自己的方法,不仅有property slots,也包含method slots。除此之外还包含key-value slots;因此他们总共有三种slots, 而常见的对象只有属性槽。
js对象是由一系列的name-value 组成的slot。而name 可以是属性名称,函数名称,映射名称。对象可通过一种特定的方式创建,使用js 对象声明语法(json),而不需要实例化一个类。代码如下:
var person1 = { lastname:smith, firstname:tom};var o1 = object.create( null); // an empty object with no slots
如果slot 的name 是合法的js 标识符,则slot可表示属性,方法,或键值对。如果名称含有一些特殊字符如空格,则slot代表键值对,是一种映射元素,如下:
property slot 中的name:
1. data value 属性,在这种情况下,value 表示变量值,或是值表达式。
2. object-valued 属性,value 表示对象的引用或对象表达式。
method slot 表示的是js 函数,它的值是js 函数定义表达式:
object 属性可以使用两种方法来访问:
1. 使用”.”(与c++ 和java的类似):
person1.lastname = smith
2. 使用map:
person1[lastname] = smith
js 对象能够用于各种途径,以下是五种常见情况:
1. record是property slots集合,如:
var myrecord = {firstname:tom, lastname:smith, age:26}
2. map 如hash map,数组,hash表;
var numeral2number = {one:1, two:2, three:3}
3. untyped 对象不需要实例化类,它可能包含property slot 和function slots:
var person1 = { lastname: smith, firstname: tom, getfullname: function () { return this.firstname + + this.lastname; } };array list
js array 即逻辑数据结构,通过数组下标访问。如数组初始化:
var a = [1,2,3];
js数组可动态增长,因此数组索引有可能比实际元素个数多,如下:
a[4] = 7;
数组循环:
for (i=0; i -1) ...
循环:
var i=0;for (i=0; i < a.length; i++) { console.log( a[i]);}
如果数组较小,可使用foreach 循环:
a.foreach( function (elem) { console.log( elem);})
js 也提供克隆数组的函数:
var clone = a.slice(0);
三、maps
map 提供key 到值得映射。js map 是一串字符集,可包含空格:
var mytranslation = { my house: mein haus, my boat: mein boot, my horse: mein pferd}
增加:
mytranslation[my car] = mein auto;
删除:
mytranslation[my car] = mein auto;
查找:
if (my bike in mytranslation) ...
循环:
var i=0, key=, keys=[];
keys = object.keys( m);
for (i=0; i < keys.length; i++) {
key = keys[i];
console.log( m[key]);
}
如果map 较小可使用foreach 语句:
object.keys( m).foreach( function (key) {
console.log( m[key]);
})
复制map
var clone = json.parse( json.stringify( m))
小结:javascript 支持4种基本的数据结构。
1:array lists:如[one,two,three],special js对象
2:records:特殊的js 对象,如{firstname:tom, lastname:smith};
3:maps: 如{one:1, two:2, three:3}
4:entity 表:如下表所示,是一种特殊的map,值是有固定id的记录。
record,map,entity 在实际应用中没有明显的区分,只是概念上的区分。对js 引擎而言,都是对象。但是从概念上是有区分的。
四、函数
如表1 所示,函数是特殊的js 对象,有name 属性和length属性表示参数的个数,如下,判断v是否指向函数:
if (typeof( v) === function) {...}
函数定义:
var myfunction = function thenameofmyfunction () {...}
thenameofmyfunction 是可选的,如果省略函数名称,则称该函数为匿名函数。通常,函数是通过变量来调用的,如上面的代码,则表示
myfunction 会调用myfunction()函数,而不是使用thenameofmyfunction()调用。
匿名函数表达式在其他编程语言中称为lambda 表达式。如下代码是匿名函数。可以与预定义的sort函数对比:
var list = [[1,2],[1,3],[1,1],[2,1]]; list.sort( function (x,y) { return ((x[0] === y[0]) ? x[1]-y[1] : x[0]-y[0]);});
函数声明:
function thenameofmyfunction () {...}
与代码
var thenameofmyfunction = function thenameofmyfunction () {...}
等价;
声明了函数thenameofmyfunction ,并使用thenameofmyfunction 变量来引用函数。
js 提供函数内联,closure机制允许js 函数调用函数之外的使用变量。函数可以创建closure 来存储当前的环境。如下,不需要通过参数将外部变量的结果传给内部函数,它本身就是可用的。
var sum = function (numbers) { var result = 0; numbers.foreach( function (n) { result += n; }); return result;};console.log( sum([1,2,3,4]));
当执行一个方法时,可以使用内置arguments 对象访问函数内的参数,arguments 对象与数组使用方法类似,有长度属性,也有索引,并且可以使用for语句来循环迭代。但是由于它并不是array 实例,因此js arrary的部分方法无法应用如foreach。
arguments 对象的元素个数与函数参数个数相同,也可以定义方法的时候不指定参数个数,在调用时,可为函数赋多个参数,如:
var sum = function () { var result = 0, i=0; for (i=0; i < arguments.length; i++) { result = result + arguments[i]; } return result;};console.log( sum(0,1,1,2,3,5,8)); // 20
方法是在构造函数的原型上定义的,可以通过对象创建的构造器调用,如array.prototype.foreach;array表示构造器,调用类的实例作为上下文对象参考的,如下: 在foreach中numbers表示上下文对象:
var numbers = [1,2,3]; // create an instance of arraynumbers.foreach( function (n) { console.log( n);});
无论原型方法是否被上下文对象调用,但是只要是参数为对象,可以使用js函数的call 方法来辅助调用对象。如下,我们可以使用foreach 循环方法:
var sum = function () { var result = 0; array.prototype.foreach.call( arguments, function (n) { result = result + n; }); return result;};
function.prototype.call方法和apply都是为了改变某个函数运行时的 context 即上下文而存在的。
五、定义和使用类
类是面向对象中的基本概念,对象的实例化称为类。js中定义类需要满足以下五个需求:
1.指定类的名称,实例级别的属性和方法,类级别的属性和方法。
2. 是可预测的实力,能够用于验证是否是某一对象的实例。
3. 实例级别的属性用于检测对象的直接类型。
4. 属性继承
5.方法继承。
除此之外还支持对哦集成和多分类。
js中对类没有统一的定义规范,可以使用不同代码模式来定义类,并应用于多种不同的框架。js中最常用的定义类的方法如下:
1. 构造函数规范,可通过prototype chain实现方法继承,并支持创建新的类实例。
2. factory 对象,用于预定义object.create 方法来创建新实例。该方法中基于构造函数的继承机制可以被其他机制代替。
创建app都需要使用类,因此经常需要定义类之间的关系,所以必须保证,使用相同类
六、constructor-based classes
只有es6引入了定义基于构造器的类。新语法支持定义一些简单的类继承,具体步骤如下:
step 1.a 基类person 具有两个属性,first name 和last name,实例层的方法tostring和静态方法checklastname;
class person { constructor( first, last) { this.firstname = first; this.lastname = last; } tostring() { return this.firstname + + this.lastname; } static checklastname( ln) { if (typeof(ln)!==string || ln.trim()===) { console.log(error: + invalid last name!); } }}
step 1.b 类层次的属性定义:
person.instances = {};
在第二步中,会定义一个带有其他属性和方法的子类,也有可能重写父类的相关方法:
class student extends person { constructor( first, last, studno) { super.constructor( first, last); this.studno = studno; } // method overrides superclass method tostring() { return super.tostring() + ( + this.studno +); }}
es5中,可以定义继承基于构造器类的子类。如下:
step1.a 首先定义构造函数,能够隐式的定义类的属性并赋值;
function person( first, last) { this.firstname = first; this.lastname = last; }
注意,上述代码中的this 指的是新生成的对象,当构造函数被调用时,该对象就已经生成了。
step1.b 定义实例层的方法:
person.prototype.tostring = function () { return this.firstname + + this.lastname;}
step 1.c 定义静态方法:
person.checklastname = function (ln) { if (typeof(ln)!==string || ln.trim()===) { console.log(error: invalid last name!); }}
step 1.d 定义类层次的静态属性
person.instances = {};
step 2.a 定义子类:
1: function student( first, last, studno) {
2: // invoke superclass constructor
3: person.call( this, first, last);
4: // define and assign additional properties
5: this.studno = studno;
6: }
通过调用超类的构造函数person.call( this, ...),来创建新对象。其中this指的是student,property slots 在超类的构造函数中已经创建((firstname 和lastname) 以及其他子类相关的属性。在这种情况下可使用property inheritance 机制保证所有的属性已经被定义且被创建。
step2b,通过构造函数的prototype 属性安装method inheritance 。如下,分配了一个新对象创建子类型构造函数的prototype 属性,并做出适当的调整:
// student inherits from personstudent.prototype = object.create( person.prototype);// adjust the subtype's constructor propertystudent.prototype.constructor = student;
step2c, 重新定义子类方法重写超类方法:
student.prototype.tostring = function () { return person.prototype.tostring.call( this) + ( + this.studno + );};
基于构造器类的实例化是通过应用new 操作符来创建的,并提供合适的构造参数:
var pers1 = new person(tom,smith);
方法tostring 通过pers1. 来调用:
alert(the full name of the person are: + pers1.tostring());
在js中,prototype 是具有method slots 的对象,可以通过js方法或属性槽继承的。
七、基于factory 的类
在该方法中定义了js 对象person,含有特殊的create 方法来调用预定义的object.create方法,创建person类型的对象;
var person = { name: person, properties: { firstname: {range:nonemptystring, label:first name, writable: true, enumerable: true}, lastname: {range:nonemptystring, label:last name, writable: true, enumerable: true} }, methods: { getfullname: function () { return this.firstname + + this.lastname; } }, create: function (slots) { // create object var obj = object.create( this.methods, this.properties); // add special property for *direct type* of object object.defineproperty( obj, type, {value: this, writable: false, enumerable: true}); // initialize object object.keys( slots).foreach( function (prop) { if (prop in this.properties) obj[prop] = slots[prop]; }) return obj; }};
注意js对象person实际表示的是factory-based 类。factory-based类的实例化是通过调用它自己的create方法实现的:
var pers1 = person.create( {firstname:tom, lastname:smith});
getfullname 方法是通过pers1. 调用的,如下:
alert(the full name of the person are: + pers1.getfullname());
每个属性的声明都是使用object.create 声明的,其中包含三个参数及值,'descriptors'writable: true and enumerable: true;如上面第五行的。
是不是一篇很赞的文章,果断收藏吧!