JavaScript基础
JS一些基本概念
- JS数字类型JavaScript只有一个单一的数字类型,它在内部被表示为64位的浮点数。所以1和1.0是相同的值。值NaN是一个数值,它表示一个不能产生正常结果的运算结果。NaN不等于任何值,包括它自己。值Infinity表示所有大于1.79769313486231570e+308值
- JavaScript在被创建的时候,Unicode是一个16位的字符集,所以JavaScript中所有字符都是16位的。JavaScript没有字符类型,要表示一个字符,只须创建仅包含一个字符的字符串即可。
- js字符串 字符串有一个length属性,字符串是不可变的,一旦字符串被创建,就永远无法改变它。但通过+运算符去连接其他的字符串从而得到一个新字符串是很容易的。‘c’+’a’+’t’===’cat’是true
- 在JavaScript中下面列出的值被当作假:
false
,null
,undefined
,空字符串‘ ’
,数字0
,数字NaN
其它所有值都被当作真,包括true.字符串‘false’,以及所有对象 - typeof运算符产生的值有‘number’,‘string’,’boolean’,’undefined’,’function’和‘object’
- javascript的简单类型包括数字,字符串,布尔值(true和false),null值和undefined值。其它所有的都是对象。数字,字符串和布尔值“貌似”对象,因为它们拥有方法,但它们是不可变的。JavaScript中的对象是可变的键控集合。在JavaScript中,数组是对象,函数是对象,正则表达式是对象,当然,对象自然也是对象。对象是属性的容器,其中每个属性都拥有名字和值。属性的名字可以是包括空字符串在内的任意字符串。属性值可以是除undefined值之外的任何值。javaScript中的对象是无类别的,它对新属性的名字和值没有约束。对象适合用于收集和管理数据。对象可以包含其他对象。javascript包括一个原型链特性。允许对象继承另一个对象的属性。正确地使用它能减少对象初始化的时间和内存消耗。
- 对象字面量:对象字面量提供了一种非常方便地创建新对象值的表示法。一个对象字面量就是包围在一对花括号中的零或多个“名/值”对。逗号用来分隔多个“名/值”对。属性的值可以从包括另一个对象字面量在内的任意表达式中获得。对象是可嵌套的。
检索:要检索对象中包含的值,可以采用在[]后缀中括住一个字符串表达式。如果字符串表达式是一个常数,而且它是一个合法的JavaScript标识符而并非保留字,那么也可以用.表示法代替,优先考虑使用
.
表示法。 stooge[‘first-name’] flight.departure.IATA
如果你检索一个并不存在的成员元素的值,将返回一个undefined值。||运算科符可以用来填充默认值: var middle = stooge['middle-name'] || "(none)" var status = flight.status || "unknown";
尝试检索一个undefined值将会导致TypeError异常。可以通过&&运算符来避免错误
更新:对象中的值可以通过赋值语句来更新。如果属性名已经存在于对象中,那么这个属性的值被替换。如果对象之前并没有拥有那个属性名,那么该属性就被扩充到该对象中。
引用 对象通过引用来传递。它们永远不会被拷贝。
原型 每个对象都连接到一个原型对象,并用它可以从中继承属性。所有通过对象字面量创建的对象都连接到Object.prototype这个JavaScript中标准的对象。当你创建一个新对象时,你可以选择某个对象作为它的原型。JavaScript提供的实现机制杂乱而复杂,但其实它可以被明显地简化。我们将给Object增加一个beget方法,使用这个beget方法创建一个使用原对象作为其原型的新对象。
if(typeof Object.beget !== 'function'){ Object.beget = function(o){ var F = function(){}; F.prototype = o; return new F(); }; } var another_stooge = Object.beget(stooge);
原型连接在更新时是不起作用的,当我们对某个对象做出改变时,不会触及到该对象的原型。
原型连接只有在检索值的时候才被用到。如果我们尝试去获取对象的某个属性值,且该对象没有此属性名,那么JavaScript会试着从原型对象中获取属性值。如果那个原型对象也没有该属性,那么再从它的原型中寻找,依此类推,直到该过程最后到达终点Object.prototype.如果想要的属性完全不存在于原型链中,那么结果就是undefined值。这个过程称为“委托”。原型关系是一种动态的关系。如果我们添加一个新的属性到原型中,该属性立即对所有基于该原型创建的对象可见。
反射 注意原型链中的任何属性都会产生一个值。有两个方法去处理这些不需要的属性。第一个是让你的程序检查并剔除函数值。一般来说做反射的目标是数据,因此你应该意识到一些值可能会是函数。另一个方法是使用hasOwnProperty方法,如果对象拥有独有的属性,它将返回true。hasOwnProperty方法不会检查原型链。
枚举
for in
语句可用来遍历一个对象中的所有属性名。该枚举过程会列出所有的属性—包括函数和你可能不关心的原型中的属性—-所以在必要过滤掉那些你不想要的值。最为常用的过滤器是hasOwnProperty
方法,可以用typeof
来排除函数;var name; for(name in another_stooge){ if(typeof another_stooge[name] !=='function'){ document.writeln(name + ':'+another_stooge[name]); } }//属性名出现的顺序是不确定的。
删除
delete
运算符可以用来删除对象的属性。它将会移除对象中确定包含的属性,它不会触及原型链中的任何对象。删除对象的属性可能会让来自原型链中的属性浮现出来减少全局变量污染 javaScript可以很随意地定义那些可保存所有应用资源的全局变量。不幸的 ,全局变量消弱了程序的灵活性,所以应该避免。最小化使用全局变量的一个方法是在你的应用中只创建唯一一个全局变量。
var MYAPP= {};
函数对象 在JavaScript中函数就是对象。对象是“名/值”对的集合并拥有一个连接到原型对象的隐藏连接。对象字面量产生的对象连接到Object.prototype。函数对象连接到Function.prototype(该原型对象本身连接到Object.prototype).每个函数在创建时附加有两个附加的隐藏属性:函数的上下文和实现函数行为的代码(JavaScript创建一个函数对象时,会给该对象设置一个‘调用’属性。当JavaScript调用一个函数时,可理解为调用此函数的‘调用’属性)。
每个函数对象在创建时也随带有一个prototype属性,它的值是一个拥有constructor属该且值即为该函数的对象。这和隐藏连接到Function.prototype完全不同。
因为函数是对象,所以它们可以像任何其他的值一样被使用。函数可以存放在变量,对象和数组中,函数可以被当作参数传递给其他函数,函数也可以再返回函数,而且,因为函数是对象,所以函数可以拥有方法。
函数的与众不同之外在于它们可以被调用。函数字面量 函数对象可以通过函数字面量来创建:
var add = function(a,b){ return a+ b;}
函数字面量包括4个部分。第一个部分是保留字function.第二个部分是函数名,它可以被省略。函数可以用它的名字来递归地调用自己。如果没有给函数命名,它就匿名函数。函数的第三个部分是包围在圆括号中的一组参数。其中每个参数用逗号分隔。这些名称被定义为函数中的变量。它们不像变通的变量那样被初始化为undefined,而是在该函数被调用时初始化为实际提供的参数的值。第四部分是包围在花括号中的一组语句。函数字面量可以出现在任何允许表达式的地方。函数也可以被定义在其他函数中。一个内部函数自然可以访问自己的参数和变量,同时它也能方便地访问它被嵌套在其中的那个函数的参数与变量。通过函数字面量创建的函数对象包含一个连接到外部上下文的连接。这被称为“闭包”。它是JavaScript强大表现力的根基。调用 调用一个函数将暂停当前函数的执行,传递控制权和参数给新函数,除了声明时定义的形式参数,每个函数接收两个附加的参数:
this
和arguments
.参数this在面向对象编程中非常重要,它的值取决于调用的模式。在javascript中有4种调用模式:
方法调用
,函数调用
,构造器调用
和apply调用
。这些模式在如何初始化this上存在差异。调用运算符是跟在任何产生一个函数值的表达式之后的一对圆括号,圆括号内可包含零个或多个用逗号隔开的表达式。每个表达式产生一个参数值。每个参数值被赋予函数声明时定义的形式参数名。当实际参数的个数与形式参数的个数不匹配时不会导致运行时错误。如果实际参数值过多了,超出的参数值将被忽略,如果参数值过少,缺少的值将会被替换为undefined。对参数值不会进行类型检查:任何类型的值都可以被传递给参数。1—方法调用模式
当一个函数被保存为对象的一个属性时,我们称它为一个方法。当一个方法被调用时,this被绑定到该对象。如果一个调用表达式包含一个属性存取表达式(即一个.点表达式或[]下标表达式),那么它被当作一个方法来调用。
//创建myObject,它有一个value属性和一个increment方法 //increment方法接受一个可选的参数。如果参数不是数字,那么默认使用数字1 var myObject = { value:0; increment:function(inc){ this.value += typeof inc==='number'?inc:1; }}; myObject.increment(); document.writelen(myObject.value);//1 myObject.increment(); document.writelen(myObject.value);//3
方法可以使用this去访问对象,所以它能从对象中取值或修改该对象。this到对象的绑定发生在调用的时候。这个“超级”迟绑定使得函数可以对this高度复用。通过this可取得它们所属对象的上下文的方法称为公共方法。
2—函数调用模式
当一个函数并非一个对象的属性时,那么它被当作一个函数来调用:
var sun = add(3,4);
//sun的值为7. 当函数以此模式调用时,this被绑定到全局对象。这是语言设计上的一个错误。倘若语言设计正确,当内部函数被调用时,this应该仍然绑定到外部函数的this变量。这个设计错误的后果是方法不能利用内部函数来帮助它工作,因为内部函数的this被绑定了错误的值,所以不能共享该方法对对象的访问权。幸运的是,有一个很容易的解决方案:如果该方法定义一个变量并给它赋值为this,那么内部函数就可以通过那个变量访问到this.按照约定,我给那个变量命名为that;//给myObject增加一个double方法 myObject.double = function(){ var that = this;//解决方法 var helper = function(){ that.value = add(that.value,that.value); }; helper();//以函数形式调用helper }; //以方法的形式调用double myObject.double(); document.writelen(myObject.getValue());//6
3—>构造器调用模式
javascript是一门基于原型继承的语言。这意味着对象可以直接从其他对象继承属性。该语言是无类别的。 如果在一个函数前面带上
new
来调用,那么将创建一个隐藏连接到该函数的prototype
成员的新对象,同时this
将会被绑定到那个新对象上。//创建一个名为Quo的构造器对象。它构造一个带有status属性的对象 var Quo = function(String){ this.status = string; }; //给Quo的所有实例提供一个名为get_status的公共方法。 Quo.prototype.get_status = function(){ return this.status; }; //构造一个Quo实例 var myQuo = new Quo("confused"); document.writeln{myQuo.get_status()};//令人困惑
目的就是结合new前缀调用的函数就是构造器函数。按照约定,它们保存以大写格式命名的变量里。如果调用构造器函数时没有在前面加上new ,可能发生非常糟糕的事情,即没有编译时警告,也没有运行时警告,所以大写给定非常重要。 不推荐使用这种形式的构造器函数
3—>Apply调用模式
因为javascript是一门函数式的面向对象编程语言,所以函数可以拥有方法。
apply
方法让我们构建一个参数数组并用其去调用函数。它也允许我们选择this
的值。apply方法接收两个参数。第一个是将被绑定给this的值。第二个就是一个参数数组。//构造一个包含两个数字的数组,并将它们相加。 var array = {3,4}; var sun = add.apply{null,array};//sum值为7 //构造一个包含status成员的对象 var statusObject = { status:'A-ok' }; //statusObject并没有继承自Quo.prototype,但我们可以在statusObject上调 //用get_status方法,尽管statusObject并没有一个名为get_status的方法。 var status = Quo.prototype.get_status.apply{statusObject}; //status值为“A-OK”
参数
当函数被调用时,会得到一个“免费”奉送的参数,那就是arguments
数组。通过它函数可以访问所有它被调用时传递给它的参数列表,包括那些没有被分配给函数声明时定义的形式参数的多余参数。
arguments并不是一个真正的数组。它只是一个“类似数组”的对象。arguments拥有一个length属性,但它缺少所有的数组方法。返回
return语句可用来使函数提前返回。一个函数总是会返回一个值,如果没有指定返回值,则返回undefined
.
异常
var add = fucntion(a,b){ if(typeof a !=='number' || typeof b !=='number' ){ throw{ name:'TypeError', message:'add needs numbers'}; } return a + b; }
throw语句中断函数的执行,它应该抛出一个exception对象,该对象包含可识别异常类型的name属性和一个描述性的message属性。你也可添加其他属性。
给类型增加方法
javascript允许给语言的基本类型增加方法。通过Object.prototype添加方法来使得该方法对所有对象可用。这样的方式对函数,数组,字符串,数字,正则表达式和布尔值同样适用。举例来说,我们可以通过给Function.prototype增加方法来使得该方法对所有函数可用模块
模块是一个提供接口却隐藏状态与实现的函数或对象。通过使用函数去产生模块,我们几乎可以完全摒弃全局变量的使用,从而缓解这个JavaScript的最为糟糕的特性之一所带来的影响。级联
有一些方法没有返回值,如,一些设置或修改对象的某个状态却不返回任何值的方法就是典型的例子。如果我们让这些方法返回this而不是undefined,就可以启用级联。在一个级联中,我们可以在单独一条语句中依次调用同一个对象的很多方法。套用
套用允许我们将函数与传递给它的参数相结合产生一个新的函数var add1 = add.curry(1); document.writeln(add1(6));//7
add1是把1传递给add函数的curry方法后创建的一个函数。add1函数把传递给它的参数的值加1.
继承
js是一门弱类型语言,从不需要类型转换,对象的起源是无关紧要的。对于一个对象来说重要的是它能做什么,而不是它从那里来。
JS常用的函数,对象等
转义字符
\b
退格字符
\f
换页符
\n
换行字符
\r
回车字符
\t
制表符
\'
单引号
\"
双引号
\\
反斜线
\xNN
其中NN是一个十六进制数,表示Latin-1字符集中的编号来表示一个字
parseInt()函数与parseFloat()函数把字符串转换为整数和浮点数
这两个函数逐字解析,如果解析到的字符不是有效数字,解析将停止,并把解析到之前的字符串转换为对应的数值。如parseInt(“123abc”)将返回数值123,当javascript解析到a字符a时,将认为字符串的数字部分已经结束。parseFloat()与parseInt()的工作方式一样,只是它把小数点也当作数字的一部分。如果没有数字将返回NaN
数组
创建数组 var myArray = new Array();
(区分大小写)。
限定长度 var myArray = new Array(6)
;也可以 var myArray = new Array('Paul',33,"john",112)
;
在javascript中数组长度是可以修改的,如我们定义了一个长度为3的数组 var myArray = new Array(3)
; 然后,为索引130的元素定义一个值 myArray[130]="Paul"
;那么JavaScript将认为我们修改了myArray数组的长度,并把myArray数组定义为长度131,即至少可以包含131个元素的数组。javascript模拟多维数组,并不存在,但可以模拟出来
var personnel = new Array();
personnel[0] = new Array();
personnel[0][0] = "name0";
personnel[0][1] = "age0";
字符串
字符串之间也可以进行比较,所有应用于数值的比较也可以应用于字符串,唯一不同的是字符串的比较是按字母顺序时行比较。toUpperCase()将字符串转换为大写形式。toLowerCase()将字符串转换为小写形式。
JavaScript的内建对象
String对象
当把一个字符串对象与一个基本数据类型的字符串比较时,将会比较实际的字符串值是否相等,但比较两个String对象时,比较的是两个对象的引入是否相等。对于String对象的部分方法来说,我们都可以将字符串视为一个由单个字符所组成的系列。每个字符具有一个索引,表示该字符在字符串中位置。
- length属性
- charAt()方法获取参数位置的字符
- charCodeAt()方法获取参数位置字符的Unicode编码
- fromCharCode()方法将字符编码转换为字符串,它与上面的方法相反,它是String的一个静态方法,我们可以直接调用String.fromCharCode(65,66);
- indexOf()和lastIndexOf()查找子串在字符串中的位置,它们具有两个参数,需要查找的子串,从哪个位置开始查找子串(可选)找到返回位置,找不到返回-1
- substr()方法和substring()方法复制字符串的一个字串,两个方法的不同之处在于参数,第一个参数都表示起始位置,第二个参数可选,如果没有表示到字串的结束。substr()方法的第二个参数表示获得子串的长度。substring()方法的第二个参数表示到达的位置,即两个位置之前的子串,包头不包尾。
Math对象
javascript中的math对象的与众不同之处在于,它是一个全局对象,在使用math对象之前,不需要声明也不需要定义一个新的,javascript将自动创建好Math对象,我们直接使用它即可。
Math对象包含一些经常使用的数学常量,如PI属性
常见的数学方法有:
- abs()方法返回传入参数的绝对值
- ceil()方法向上取整
- floor()方法向下取整
- round()方法用于对一个整数进行四舍五入
- random()方法返回一个0到1之间的随机数,包含0但不包含1
- pow()方法用于计算一个数的指定幂pow(n,m)n为底数,m为幂
Number对象
与String对象类似,我们需要先创建一个Number对象,然后才能使用Number对象的各种方法和属性。
- toFixed()方法用于截取指定小数点位数的数字,参数为截取的小数的位数,此方法在截取位数的同时会四舍五入。
Array对象
concat()方法 连接两个数组,可以把两个单独的数组连接在一起,形成一个新的数组,第一个数组调用此方法,将第二个数组对象传进去
slice()方法,获取数组的部分元素,返回值也是一个数组对象,两个参数欲复制数组元素的起始索引,表示所复制数组元素的结束位置边界的数组元素的索引(可选参数)
join()方法,将数组转换为字符串,并将这些字符串连接成一个完整的字符串,仅有一个参数就是连接数组元素的分隔符。
sort()方法 对数组进行排序,升序
reverse()方法 反转数组中元素的顺序,与sort()方法联合使用可以达到降序效果
Date对象
- getDate()返回一个整数,表示当前日期是月份中的第几天
- getDay()方法,返回一个整数,表示当前日期是星期几,0表示星期日依此类推
- getMonth()返回一个表示当前月份的整数,0表示1月
- getFullYear()返回一个以4位数表示的年份
- getDateStrig()基于当前时区,返回一个人们可以理解的日期字符串
setDate()
,setMonth()
,setFullYear()
;没有setDay()
因为当年月日确定后,星期几就确定了
设置的值如果超出了以上三个函数的范围,则他们会从第一天或月或年算起加上设置的值(可以是负值)进行计算得到新日期。所以计算某一年之后的28天就可以用如下代码
var nowDate = new Date();
var currentDay = newDate.getDate();
nowDate.setDate(currentDay + 28);
获取时间的值getHours()
,getMinutes()
,getSeconds()
,getMilliseconds()
,toTimeString()
,getMilliseconds()
javascript中的类
构造函数的名称与类名完全相同,在javascript中无需定义好类属性,只需要为属性附值,javascript将自动创建这些属性,对象同样如此,javascript中的大部分对象都具有prototype属性,通过prototype属性可以创建新的属性和方法