学习目标
JavaScript目前是十分热门的语言了,百花争鸣,衍生出了大量可以用于多种平台的框架。例如用于Web端的JQuery,用于搭建服务器的Node.js,用于开发移动应用的React Navite,使用的范围实在太广了。这次的学习目标主要了解JavaScript相关的语法规则和其特有的思想,从而,可以使用JavaScript语言开发移动H5版本的应用,使用React Native开发移动应用。
学习过程
1、搜索相关入门资料。知乎搜索“入门JavaScript”,看看入坑多年的人怎么推荐。由于想要系统性的学习一遍,系统性学习的话最好是看官网的入门资料或者书籍,最终决定通过《JavaScript权威指南》入坑。 2、通过runjs网站 实践里面的例子,后期搭建本地JavaScript开发环境,使用了Sublime与Node.js。 2、选读某些章节,有针对性的阅读,并通过Sublime动手实践。例如表达式基本都是通用的,这部分就快速的略过,其他JavaScript特有的特性,则需要细细的阅读。 3、每阅读一个章节,写一篇总结。
总结
前篇
- JavaScript采用UTF-16的Unicode字符集编码.
- JavaScript区分大小写.
类型、值和变量
- 变量声明。变量有两种声明方式。var和const。const声明的关键字值不可更改,var可以。
var x = 1;//可更改 x = 2;//正确 const y = 2; y = 3; //错误 复制代码
- 数据类型。JavaScript有三种类型,原始类型、对象类型、undefined类型。其中原始类型包括数字、字符串、布尔值。undefined表示变量未被定义。对象类型下面会说明。
- 对象类型。Javascript的对象概念与Java不同,这个十分重要。JavaScript的对象是属性的集合,每个属性都由"名称/值"构成。对象有三种:普通对象、Array(代表有序集合)、null(特殊对象).
- 对象管理。JavaScript对象有自己的内存管理机制,不需要我们关心销毁和回收。
- 数字。JavaScript中所有的数字只有一种类型:浮点型。
- 数字常量。JavaScript预定义了Infinity和NaN。分别表示着正无穷大和非数字值。
- 布尔类型。"false,null,undefined,0,-0,NaN"都是假值,其他都是真值,包括负数也是真值。这点与Java不同。
- null&undefined。JavaScript中null用来描述空值。而undefinede表示变量为被初始化,当函数没有返回值的时候,强行获取该返回值会返回undefined.
- 全局对象。JavaScript从作用范围的角度看,有一类特殊的对象,全局对象。全局对象可以在任意一个地方使用,如果我们在函数外面声明了全局变量,它就属于全局对象的属性之一。
- 类型转换。JavaScript对不同类型的变量进行操作时,会自动进行类型转换。
- 类型包装。可以将原始变量包装成对象进行操作,这点与Java一样。
- 对象基本操作方法。所有对象都默认继承了toString()和valueOf()方法。这点与Java中默认继承Object是类似的。
- 变量作用域。函数内变量声明则在函数内有效,函数外则是全局作用域,函数内变量比全局变量优先级高,JavaScript有一个声明提前的特性,无论在函数内哪个地方声明变量,执行的时候,都会被最先执行到。
var scope = "global";//全局变量 function checkScope(){ console.log(scope);//这里会输出undefined 而不是 global. var scope = "local"; console.log(scope);//输出local. } 复制代码
表达式和运算符
-
数组声明。
var array = [];//空数组 var array = [1,2];//两个元素 va array = [[1,2,3,],[1,2,3]];//两维数组 var array = [1,,,5];//这里有5个元素,其中逗号占位的元素初始值为undefined. 复制代码
-
对象声明。
var object = {x:2.3,y:1.2};//声明了属性,x,y并赋值。 var object ={}; object.z = 12;//这里定义了属性z; var object = {upperLeft :{x:2,y:2}};//对象声明也可以嵌套 复制代码
-
函数也是对象的一种。
-
对象属性访问。
var o = {x:1,y:{z:3}}; o.x //结果为1 o["x"];//结果也是1 复制代码
-
对象创建可以使用new关键字。
-
加号。JavaScript中加号操作符允许多种情况相加,例如数字可以直接和字符串相加,加号的转换规则优先考虑字符串连接。
1+2 //结果3 "1"+"2"// 结果12 1+“2”//结果12 1+2+ “test”//结果 3 test; 复制代码
-
===相等符。严格相等符号,判断过程中不进行任何类型。转换遵循以下规则:
-
两个值类型不同,不相等
-
其中一个值为NaN,不等。
-
同一个引用,相等。
-
==相等符号。不严格相等符。如果不同类型比较,会转换类型后比较。遵循以下规则:
-
一个为null,一个为undefined,相等
-
如果数字与字符串比较,会将字符串转为数字,两个数字相等就相等。
-
如果是true 转换为1,false转换为0,再比较。
-
in 运算符。左操作符是字符串或者可以转换成字符串,右操作是一个对象。作用是判断右侧对象是否存在左侧的属性或者方法、或者索引。注意这个运算符无法通过判断值是否已定义。
var point = {x:1}; "x" in point ;//point是否存在属性x var data = [1,3]; "1" in data ;//是否存在索引1,如果该索引下的值是undefined的话,那么会返回false 复制代码
-
instanceof 运算符。与Java一致。
var array = [1,2]; array instanceof Object ;//结果为true 复制代码
-
typeof 运算符。返回操作数的类型。
var array = [1,3]; typeof array ;//返回 object. typeof true //返回 boolean typeof 任意数字;//number tyopeof 字符串 ;//string typeof 函数 ;//function typeof 内置对象;//object 复制代码
-
delete运算符.删除对象属性或者数组元素.
var o = {x:1,y:2}; delete o.x; "x" in o;//false,因为删除了x; 复制代码
语句
-
函数声明。
function 函数名 (参数名列表..){ } //例子 function func(x,y){ } 复制代码
-
其他控制语句与Java一致。
-
for/in。JavaScrpit提供了类似与Java的foreach循环遍历语句.遍历获取到的是属性,而非属性值,这一点与Java不同。如果遍历对象是null或者undefined,JavaScrpit会跳过该for/in语句,继续执行下面的代码。
//语法 for(变量 in 遍历对象){ } ///例子: for(var p in o ){ console.log(o[p]); //打印o对象的值 } 复制代码
-
跳转语句与Java基本一致,不同的一点是语句可以添加标签,break和continue 支持跳出某个标签。
mainloop:while(token !=null){ contnue mainloop;//跳出mainloop } 复制代码
-
JavaScript异常处理与Java一致。不同的是JavaScript异常处理不支持精确的异常匹配,只能获取一个异常值。
try{ }catch(e){ } finally{ } 复制代码
-
debugger.调试时候用,为语句添加断点。
function f(o){ if(o === undefined) debugger;//当调试的时候,在这里会停住。 } 复制代码
对象
-
对象是键值对的集合。
-
除了字符串、数字、true、false、null、undefined之外,JavaScript中其他的值都是对象。
-
对象常见用法是创建、赋值、查找、删除、遍历。
-
对象类别:内置对象(例如日期、数组等,JavaScript自定义)、宿主对象(由JavaScript嵌入的宿主环境,例如浏览器定义)。自定义对象(开发者自定义的对象)。
-
创建对象。对象有三种创建形式。一种是使用对象直接量,一种是通过new 关键字。一种是通过Obejct.create()方法。
//对象直接量 var empty = {};//通过{}直接声明。 //通过new关键字。 var o = new Object(); //通过Object.create() var o1 = Object.create({x:1,y:2}); 复制代码
-
查询和赋值。通过.和[]下标索引就可以得到值。
-
获取对象属性。可以通过for 或者 for/in获取可枚举的属性。如果需要获取不可以枚举的属性,可以通过 Object.getOwnPropertyNames()。另外可以通过以下函数获取对象全部属性。
//获取参数自身的所有属性: getAllProperties(Math) // 获取参数自身和原型链上的所有属性: getAllProperties(Math, true) function getAllProperties(obj, getProtoProperties) { var names = Object.getOwnPropertyNames(obj); var namesObj = {'funcProper':[], 'properties':[]}; names.forEach(function(value, key) { if(typeof obj[value] === 'function') namesObj['funcProper'].push(value); else namesObj['properties'].push(value); }); if(getProtoProperties && obj.__proto__) namesObj['protoProperties'] = getAllProperties(obj.__proto__, getProtoProperties); return namesObj; } 复制代码
-
继承。通过inhert()可以继承对象。被继承的属性值可以被覆盖。
var o = {r:1}; var p = inherit(o); o.r = 3;//这里覆盖了o原型的r属性。 复制代码
-
删除属性。js中属性可以被删除,并且只能删除自己的属性,无法删除原型属性。并且不能删除哪些可配置型为false的属性。
var o = {o:1}; delete o.x; 复制代码
-
检测属性是否存在。
//通过in符。可检测继承属性或者自有属性。 var o = {x:1}; "x" in o ; //通过 hasOwnProperty();检查自有属性 var o = {x:1}; o.hasOwnProperty("x"); //通过propertyisEnumerable();检测自有属性,需要该属性是可枚举的。 var o ={x:1}; o.propertyIsEnumrable("x"); //也可以通过判断是否等于undefined. if(o.x ===undefined){ } 复制代码
-
getter和setter.对象的属性可以分为存取器属性和数据属性。存取属性就是用get和set描述的属性。如果只是声明了get属性,那么该属性无法被重新赋值。
get 属性名(){} set 属性名(){} //例子 var o = { normal:"normal", get accessor(){}//这里定义了存取属性的get方法 set accessor(vale){} } 复制代码
-
$符号。通过$描述的属性是私有属性。
-
属性的特性。属性有两个共同的特性,一个是可枚举性,一个是可配置性。而数据属性有值和可写性。存取器有 取 和写入特性。
Object.getOwnPropertyDescriptor()//获取对象自有特定属性的特性。 Object.getOwnPropertyDescriptor{{x:1},"x"};//获取x属性的特性。 Object.defineProperty()//更改属性。 复制代码
-
属性设置的规则:
- 如果对象是不可扩展的,可以编辑已有自有属性,不能添加新属性
- 属性不可配置,不能修改该属性任何特性,同时也不能数据属性/存取属性互转。但可以将可写性变为false,
- 如果数据属性是不可配置且不可写,则不能修改它的值。如果可配置但不可写,那么可以修改。
- 对象有三个对象级的属性。一个是原型,一个是类属性,一个是可扩展性。原型就是它继承的对象,类属性就是类信息,可扩展性就是类是否可以添加新属性。
-
原型属性。通过对象直接量创建的对象默认使用了Object.prototype作为它们的原型。通过new关键字,那么使用的构造函数的prototype就是它们的原型。
Object.getPrototypeOf(对象);//获取该对象的原型属性 var b = {}; var o = {}; b.isPrototypeOf(o);//o是否是b的原型属性。跟Instanceof相似 复制代码
-
可扩展性。判断是否可以给对象添加新属性。
Object.isExtensible(对象);//是否可以扩展 Object.preventExtensions();//将对象设置为不可扩展,注意这个过程不可逆转。 Object.seal)();//不可扩展,属性不可删除或者配置。 Object.freeze();//对象不可扩展,不可修改添加,数据属性会被设置为只读。 复制代码
-
序列化。内置了JSON.stringify()和JSON.parse();序列化和反序列对象。
-
对象基本方法。
toString();// toLocaleString(); toJSON();//序列化对象 valueOf();//跟toString类似.需要将对象转为某种原始值才使用。 复制代码
数组
-
创建数组。数组创建有两种方式。一种是数组直接量,一种是使用Array()类直接构建。
//数组直接量 var array = [2,3,4]; // 使用 Array()构造函数。 var array = new Array(); 复制代码
-
读取数组。可以使用下标读取数组和循环语句读取数组。
-
稀疏数组。包含从0开始的不连续索引的数组。
-
数组的长度length.数组中有一个length值。它遵循以下规则。
- 向数组添加下标非数字,length不会+1,但是数组里面会有这样一个键值对。
var array =[1,2,3]; array["x"] =2;//array.lenght还是3,x是一个新的键值对。 复制代码
- 向数组添加大于当前length的下标,那么该数组的长度将会变成下标+1。
var array = [1,2,3]; array[23] = 3;//length会变成24.且数组的元素多出20个undefine的元素。 复制代码
- 向数组添加下标非数字,length不会+1,但是数组里面会有这样一个键值对。
-
将array.length设置为小于length的值,会截断数组。
var array = [1,2,3]; array.length = 1;//array 变成了 [1]。 复制代码
-
数组常用方法。
var array = [1,2,3]; 复制代码
-
push().末尾添加元素。array.push("value");会更改长度。
-
pop().末尾删除元素。会更改长度。
-
删除元素。delete array[0i];//删除下标0的元素,该元素变成了undefined.不影响长度。
-
join()。将数组按照某种格式连接。array.join("-");//1-2-3;
-
reverse();将数组倒叙
-
sort().排序。默认按照字母表排序。可以自己定义排序方法。
-
concat()。创建一个新数组。
-
unshft().头部删除元素。会改变长度。
-
shift()。头部添加元素。会改变长度。
-
数组类属性为"Array".
函数
-
函数的定义&创建。
//常用定义方式 function 函数名称(参数名称){ } //匿名函数. function(参数名称){ } //通过Function类创建。 var function = new Function{"x","y","return x+y"}; 复制代码
-
参数。函数不要求传入的实际参数与声明的参数个数相同。但是可以通过可选参数,显式声明那些是可选的。使用optional修饰可选参数名。
function test(a, optional test){ } 复制代码
-
参数列表。函数也是对象,函数里面的arguments属性就是参数列表。
-
重载。JS不存在函数重载。后面声明的函数会覆盖前面的函数。
-
函数属性。因为函数也是对象,所以可以给函数添加属性。
-
常用属性以及方法。
-
实参个数。函数里面的arguments.length标识传入函数实参的个数。
-
期待传入的参数个数。arguments.callee.length.
- Function构造函数。使用Function创建函数的话,函数体的编译会在顶层函数执行。
例如: var scope = "global"; function f1(){ var scope = "f1 local"; return new Function("return scope"); } f1();//这里会打印global.而不是f1 local. 复制代码
-
函数的类原型是.function.
类和模块
-
定义类。类在类型上实际是一个函数function类型。类的定义方式有下面两种。
-
方式1.直接覆盖prototype对象。
//范式 function className(){ //对象 } className.prototype{ //定义函数键值对和属性. //记住需要重新赋值constructor属性 } //例子 function Range(from ,to){ this.from = from; this.to = to; } Range.prototype= { contructor:Range; //因为prototype被覆盖,所以需要重新指定contructor. includes:function (x){return this.from <= x&&x<=this.to};//定义了方法includes } var r = new Range(1,3); r.includes(2); 复制代码
-
方式2。通过inherit方法。
//范式 function className(){ var r = inherit(className.methods); return r; } className.methods = { //定义函数键值对和属性。 } //例子 function Range(from,to){ var r = inherit(Range.methods);//继承了它的方法。 r.from = from; r.to = to; return r; } Range.methods = { includes:function (x){return this.from <= x&&x<=this.to};//定义了方法includes } 方式1调用: var r = Range(1,3); r.include(2); 复制代码
-
prototype和constructor.每个JS对象都包括了一个prototype,表示该对象的原型,在prototype里面,还默认包括了constructor属性,这是一个函数对象,表示当前类。
-
定义子类。
function classA{ } function classB(){ } 如果要让A继承B. classB.prototype = inherit(A.prototype);//继承A的原型属性。 classB.constructor = B;//重新设置该类的类型 复制代码
-
命名空间。js采用对象的形式实现。
var utils = {};/定义了uitls包 utils.List = {}//给utils包添加了List包; utils.List.ArrayList = ArrayList;//添加了ArrayList类 复制代码