JavaScript 快速踩坑(1)

JavaScript语言核心

1.JavaScript概述

JavaScript语言核心

  • JavaScript中最重要的类型就是对象,对象是由花括号扩起来的
var book ={              
    topic: "javascript", 
    fat:true
}
  • 将函数和对象合写到一起时,函数就变成了“方法”
    **

2. 词法结构

字符集

  • 许多客户端JavaScript对象和属性与它们所表示的HTML标签和属性同名。在HTML中,这些标签和属性名可以使用大写也可以是小写,而在JavaScript中则必须是小写。例如,在HTML中设置事件处理程序时,onclick属性可以写成onClick,但是在JavaScript代码中,必须使用小写onclick。

3. 类型、值和变量

  • 普通的JavaScript对象是“命名值”的无序集合。JavaScript同样定义了一种特殊对象-数组(Array),表示带编号的值的有序集合。
  • JavaScript还定义了另一种特殊对象-函数(Function)。函数是具有与它相关联的可执行代码的对象,通过调用函数来运行可执行代码,并返回运算结果。

数字

  • JavaScript不区分整数值和浮点数值。JavaScript中的所有数字均用浮点数值表示。
  • JavaScript中有一个类似的函数isFinite(),在参数不是NaN,Infinity或-Infinity时返回True
  • 负零值和正零值是相等的
var zero=0;
var nzero=-0;
console.log(zero === nzero);  //true
console.log( 1/zero === 1/nzero); //false
  • 使用浮点数进行运算时,要注意四舍五入
x=.3-.2 //实际结果是0.09999999999999998
y=.2-.1 //实际结果是0.1

布尔值

  • javascript中的undefined、null、0、-0、NaN、”” 会被转换成false
  • 布尔值包含toString()方法,因此可以使用这个方法将字符串转换为”true”或”false”

null和undefined

  • 对null执行typeof预算,结果返回字符串”object”,也就是说,可以将null认为是一种特殊的对象值,含义是”非对象”

全局对象

  • 在浏览器窗口中的所有JavaScript代码中,Window对象充当了全局对象,这个全局对象有一个属性window引用其自身,它可以代替this来引用全局对象

包装对象

  • 字符串既然不是对象,为什么它会有属性?
    只要引用了字符串s的属性,JavaScript就会将字符串值通过调用new String(s)的方式转换成对象,这个对象继承了字符串的方法。

  • 不要使用自动包装来修改属性,因为修改只是发生在临时对象上,而这个临时对象并不会继续保留下来

var s ="test";
console.log(s.len);  //undefined
s.len=4;   //此时创建一个临时字符串对象,并给其len属性赋值,随即销毁这个对象
var t= s.len; // 通过原始字符串创建一个新字符串对象,尝试读取其len属性
console.log(t);  //undefined

//正确赋值方法
var s = new String("test");
console.log(s.len); //undefined
s.len=4;
var t = s.len;
console.log(t); //4
  • “==”等于运算符将原始值和其包装对象视为相等,但”===”全等运算符将它们视为不等。通过typeof运算符可以看到原始值和其包装对象的不同

类型转换

  • 以数字表示的字符串可以直接转换为数字,也允许在开始和结尾处带有空格
  • 以下这些比较结果均是true
null == undefined
"0"==0              //比较之前均被转换成数字 
0==false            //比较之前布尔值转换成数字
"0"==false          //字符串和布尔值均转换成数字
  • Boolean()、Number()、String()或Object(),当不通过new运算符调用这些函数时,它们会作为类型转换函数
  • parseInt()和parseFloat()都会跳过任意数量的前导空格,尽可能解析更多数值字符,并忽略后面的内容
parseInt("3 blind mice")  //3
parseInt("0xFF")          //255
parseInt("0.1")           //0
parseInt(".1")            //NaN:整数不能以.开头
parseInt(.1)              //0
parseFloat("$72.47")      //NaN:数字不能以$开头
  • 对象到布尔值的转换非常简单:所有的对象均转换为true

变量作用域

  • javascript函数里声明的所有变量都被“提前”至函数体的顶部
var scope ="global"
function f(){
    console.log(scope);   //undefined
    var scope="local";
    console.log(scope);   //local
}
f();

4.表达式和运算符

运算符概述

  • 一元操作符、赋值和三元条件运算符都具有从右至左的结合性
x=~-y;             //等于 x=~(-y) 
w=x=y=z;           //等于 w=(x=(y=z));
q=a?b:c?d:e?f:g;  //等于 q=a?b:(c?d:(e?f:g))

算术表达式

  • 加号转换规则优先考虑字符串连接,若两个操作数都不是字符串,则转换成数字进行计算
"1"+2   //12
true+true  //2
  • 对象到原始值的转换规则: 日期对象通过toString()方法执行转换,其他对象则通过valueOf()方法执行转换(如果valueOf方法返回一个原始值的话)。由于多数对象都不具备可用的valueOf()方法,因此它们会通过toString()方法来执行转换。

  • 表达式++x并不总和x=x+1完全一样,如果x是字符串”1”,++x的结果就是数字2,而x+1的结果就是”11”

关系表达式

  • NaN和其他任何值都是不相等的,包括它本身!通过x!==x来判断x是否为NaN,只有在x为NaN的时候,这个表达式的值才为true
  • 使用==运算符时,如果其中一个值是true,则将其转换为1再进行比较。如果其中一个值是false,则转换为0再进行比较
  • 比较运算符
11<3        // false
"11"<"3"    // true
"11"<3      // false
"one"<3     // false
  • in运算符,其左操作符是一个字符串或可以转换成为字符串的值
var point={x:1,y:1};
"x" in point          //true
"z" in point          //false
"toString" in point   //true,对象继承了toString方法

var data=[7,8,9]
"0" in data           //true,包含0下标
1 in data             //true
3 in data             //false,不包含3下标

表达式计算

  • eval()只有一个参数。如果传入的参数不是字符串,它直接返回这个参数。如果参数是字符串,它会把字符串当成JavaScript代码进行编译,如果编译失败则抛出一个语法错误异常。如果编译成功,则开始执行这段代码,并返回字符串中的最后一个表达式或语句的值,如果最后一个表达式或语句没有值,则最终返回undefined。

5.语句

声明语句

  • var声明的变量是无法通过delete删除的
  • 函数声明语句通常出现在JavaScript代码的最顶层,也可以嵌套在其他函数体内,但在嵌套时,函数声明只能出现在所嵌套函数的顶部。
  • switch语句首先计算expression的值,然后查找case子句中的表达式是否和expression的值相同,这里的相同指的是按照”===”运算符进行比较的

循环

  • for/in循环并不会遍历对象的所有属性,只有“可枚举”的属性才会遍历到。除了内置方法之外,还有很多内置对象的属性也是“不可枚举的”。
  • 如果for/in的循环体删除了还未枚举的属性,那么这个属性将不会再枚举到。如果循环体定义了对象的新属性,这些属性通常也不会枚举到。

跳转

  • 不管break语句带不带标签,它的控制权都无法越过函数的边界。比如,对于一条带标签的函数定义语句来说,不能从函数内部通过这个标签来跳转到函数外部
  • 如果try/finally从句中,在finally从句抛出一个异常,这个异常将替代正在抛出的异常。如果finally从句运行到了return语句,尽管已经抛出了异常且这个抛出的异常还没有被处理,这个方法依然会正常返回
var foo = function(){
    try{
        throw new Error("抛出异常");
    }finally{
        return 1;
    }
}
console.log( foo());  //1

6.对象

删除属性

  • delete运算符只能删除自有属性,不能删除继承属性,要删除继承属性必须从定义这个属性的原型对象上删除它,而且这会影响到所有继承这个原型的对象。

检测属性

  • 对象的hasOwnProperty()方法用来检测给定的名字是否是对象的自由属性。对于继承属性它将返回false
  • propertyIsEnumerable()是hasOwnProperty()的增强版,只有检测到是自有属性且这个属性的可枚举性为true时它才返回true

对象的三个属性

  • 对象的原型属性是用来继承属性的,可以通过p.isPrototypeOf(o)来检测p是否是o的原型

枚举属性

  • ECMAScript 5定义了两个用以枚举属性名称的函数。第一个是Object.keys(),它返回一个数组,这个数组由对象中可枚举的自由属性的名称组成。第二个枚举属性的函数是Object.getOwnPropertyNames(),只是它返回对象的所有自由属性的名称,而不仅仅是可枚举的属性

7. 数组

数组元素的读和写

  • 数组索引仅仅是对象属性名的一种特殊形式,这意味着JavaScript数组没有“越界”错误的概念

稀疏数组

  • 稀疏数组就是包含从0开始的不连续索引的数组。通常,数组的length属性值代表数组中元素的个数。如果数组是稀疏的,length属性值大于元素的个数。

数组元素的添加和删除

  • 可以使用push()方法在数组末尾添加一个或多个元素,可以使用unshift()方法在数组的首部插入一个元素
  • 数组有pop()方法,使得长度减1并返回被删除元素的值。还有一个shift()方法,丛数组头部删除一个元素,并将所有元素下移到比当前索引低1的地方。
  • delete操作并不影响数组的长度,也不会移动数组

ECMAScript5中的数组方法

  • filter()会跳过稀疏数组中缺少的元素,它的返回数组总是稠密的。为了压缩稀疏数组的空缺,代码如下:

    var dense = sparse.filter(function(){return true;})

    甚至,压缩空缺并删除undefined和null元素,可以这样使用filter():

    a = a.filter(function(x){return x!==undefined && x!=null })

8.函数

函数调用

  • 根据ECMAScript3和非严格的ECMAScript5对函数调用的规定,调用上下文(this的值)是全局对象(若是浏览器则是window对象)。然而,在严格模式下,调用上下文则是undefined。因此,可以通过this来判断当前是否是严格模式
var nostrict = (function(){return !this;}())
  • 嵌套的函数不会从调用它的函数中继承this。如果嵌套函数作为方法调用,其this的值指向调用它的对象。如果嵌套函数作为函数调用,其this值不是全局对象(非严格模式)就是undefined(严格模式)。如果你想访问这个外部函数的this值,需要将this的值保存在一个变量里,这个变量和内部函数都同在一个作用域内。通常使用变量self来保存this,比如:
var o ={
    m:function(){
        var self = this;  // o
        console.log(this===o);
        f();

        function f(){
            console.log(this)   //window or undefined
            console.log(this ===o);  //false
            console.log(self ===o);  //true
        }
    }
}

作为值的函数

  • 如下定义匿名函数并立即在单个表达式中调用它的写法非常常见,已经成为一种惯用法。注意代码的圆括号用法,function之前的左圆括号是必须的,因为如果不写这个左圆括号,JavaScript解释器会试图将关键字function解析为函数声明语句。
(function(){
    //模块代码
}())

闭包

  • 函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。
  • 下面这段代码创建了10个闭包,当constfuncs()返回时,变量i的值是10,所有的闭包都共享这一个值,因此,数组中的函数的返回值都是同一个值(10)。嵌套的函数不会将作用域内的私有成员复制一份,也不会对所绑定的变量生成静态快照.
function constfuncs(){
    var funcs = [];
    for(var i =0;i<10;i++){
        funcs[i]=function(){return i}
    }
    return funcs;
}

var funcs = constfuncs();
var result = funcs[5]();
console.log(result); //10

9.类和模块

没有原型的对象为数不多,Object.prototype就是其中之一。

JavaScript中的面向对象技术

  • 如果将用于JavaScript的关系比较运算符,比如”<”和”<=”,JavaScript会首先调用对象的valueOf()方法,如果这个方法返回一个原始值,则直接比较原始值

10.正则表达式的模式匹配

正则表达式的定义

  • 正则表达式直接量定义为包含在一对斜杠(/)之间的字符,例如:

    var pattern = /s$/

    运行这段代码创建一个新的RegExp对象,并将它赋值给变量pattern。这个特殊的RegExp对象用来匹配所有以字母”s”结尾的字符串。

  • 正则表达式/a+/可以匹配一个或多个连续的字母a。当使用”aaa”作为匹配字符串时,正则表达式会匹配它的三个字符。但是/a+?/也可以匹配一个或多个连续字母a。但它会尽可能少地匹配

  • 字符”|”用于分割供选择的字符,/\d{3}|[a-z]{4}/匹配的是三位数字或者四个小写字母.

  • 正则表达式中的圆括号有多种作用。一个作用是把单独的项组合成子表达式,/(ab|cd)+|ef/ 可以匹配”ef”,也可以匹配”ab”或者”cd”的一次或多次重复

  • 圆括号的另一个作用是在完整的模式中定义子模式。

  • 圆括号的另一个用途是允许在同一正则表达式的后部引用前面的子表达式。比如 /([‘”])[^’”]*\1/ 可以匹配有双引号或单引号包含的字符串

  • 修饰符是放在”/”符号之外的,也就是说,它们不是出现在两条斜线之间,而是第二条斜线之后。
    修饰符如下:
    i: 执行不区分大小写的匹配
    g: 执行一个全局匹配,简言之,即找到所有的匹配,而不是在找到第一个之后就停止
    m: 多行匹配模式,^匹配一行的开头和字符串的开头,&匹配行的结束和字符串的结束

用于模式匹配的String方法

  • String支持4种使用正则表达式的方法,最简单的是search()。比如,下面的调用返回值为4:

    Javascript“.search(/script/i);

    search()方法不支持全局检索,因为它忽略正则表达式参数中的修饰符g

  • replace()方法用以执行检索与替换操作。其中第一个参数是一个正则表达式,第二个参数是要进行替换的字符串。利用replace()将文本中的所有javascript(不区分大小写)统一替换为”Javascript”:

    text.replace(/javascript/gi,"Javascript")

    比如,可以用它将一个字符串中的英文引号替换为中文半角引号:

    //一段引用文本起始于引号,结束于引号
    // 中间的内容不能包含引号
    var quote = /"([^"]*)"/g;
    //用中文半角引号替换英文引号,同时要保持引号之间的内容(存储在$1中)没有被修改
    text.replace(quote,' "$1" ')   
    
  • match()方法唯一的参数就是一个正则表达式,该方法返回的数组包含字符串中所有匹配结果,例如:

    "1 plus 2 equals 3".match(/\d+/g) //返回["1","2","3"] 

    如果这个正则表达式没有设置修饰符g,match()就不会进行全局检索,它只检索第一个匹配,但即使match()执行的不是全局检索,它也返回一个数组。在这种情况下,数组的第一个元素就是匹配的字符串,余下的元素则是正则表达式中用圆括号括起来的子表达式.

RegExp对象

  • 如果待检索的字符串是由用户输入的,就必须使用RegExp()构造函数,在程序运行时创建正则表达式。

11.服务器端JavaScript

  • Rhino是基于Java的Javascript解析器,实现了通过Javascript程序访问整个Java API。
  • Node是Google的V8 Script解析器的一个特别版本,它在底层绑定了POSIX(Unix)API,包括文件,进程,流和套接字等,并侧重于异步I/O

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值