【原创教程】JavaScript详解之语法和对象

JavaScript的好的想法:函数、弱类型、动态对象和一个富有表现力的对象字面量表示法。
JavaScript的坏的想法:基于全局变量的编程模型。
 
好了,无论他是好的仍是坏的,都是个人最爱,下面直接上干活:
1、JavaScript语法
 
一、空白:空白能可能的表现形式为格式化字符或注释的形式。
     有些空白不能省,有些空白能够被移除。
     注释,/*多行注释*/,不建议在代码块中间使用这种注释,由于可能会出现语法错误,因此多行注释对于被注释的代码来讲是不安全的。
好比:
/*
     var r_m_a = /a*/.match(s);
*/
这就致使了一个语法错误,因此建议避免使用/*  */注释,而改使用//单行注释来注释代码。
那么多行注释在何时使用呢,在对一个方法或者其余代码块进行语言说明其用途和做者等信息时候使用,好比:
/*返回两个数的和*/
function sum() {.......}
 
二、标识符
标识符由字母、数字或下划线组成的。标识符不能使用下面这些保留字:
abstract
boolean break byte 
case catch char class const continue 
debugger default delete do double
else enum export extends
false final finally float for function
goto
native new null
package private protected public
return 
short static super switch synchronized
this throw throws transient true try typeof
var volatile void
while with
在这个列表中的大部分保留字js都没有使用,这里列出了这么多,你不须要去刻意记忆,用的时候注意下,同时在编译出错的时候可以知道为何出错了。
 
三、数字
int float double?不不不,JavaScript中只有单一的数字类型,它在内部被表示为64位的浮点数。因此1和1.0是同样的。
其中有些特殊的数字:
     值NaN是一个数值,他表示一个不能产生正常结果的运算结果,NaN不等于任何值,包括他本身,是的没错,他本身都不等于他本身,你还但愿谁和它相等呢。那如何检测一个变量是否是NaN呢,用函数isNaN(number)来检测NaN,返回Boolean值;
     值Infinity表示全部大于1.77.....e+308的值,便是无穷大。那无穷小呢,加个负号呗。
数字拥有方法,例如:Math.floor( number ) 发放将一个数字转换为一个整数。
这里有一个须要注意的点,就是数值类型不含有方法,数值对象才有方法,什么是数值类型呢,像1233,231,34等这些都是数值类型,而若是 我这样来:
var  num = 234.567;
这时候mun就是数值对象,它拥有方法。
 
四、字符串
字符串字面量能够被包围在单引号或者双引号中,\ 是转义字符。JavaScript在被建立的时候,Unicode是一个16位的字符集,因此全部的字符都是16位的;字符串是没有字符类型的。要表示一个字符,只须建立仅包含一个字符的字符串便可。
上面有说到“转义字符”,那么什么是转义字符呢,转义字符容许把那些正常状况下不被容许的字符插入到字符串中,好比反斜线、引号和控制字符。 \ u 约定容许指定用数字表示字符码位。
"A" === "\u0041"
字符串有一个length属性,例如:“skylor”.length 是6.
还有一点是须要注意的,字符串是不可变的,一旦字符串被建立了,就永远没法改变它。可是经过 + 运算符去连接其余的字符串从而获得一个新的字符创是很容易的一件事。   且:::两个包含着彻底相同字符且字符顺序相同的字符串被认为是相同的字符串。so:
's' + 'k' + 'y' + 'l' + 'o' + 'r' === 'skylor'
这是个true!一样的 字符串也有一些方法。 
 
五、语句
六、表达式
     字面量(好比字符串或数字)、变量、内置的值(true、flase、null、undefined、NaN和Infinity)、以new 前导的调用表达式、以delete前导的属性存取表达式、包在圆括号中的表达式、以一个前缀运算符或者是后面跟着运算符、函数调用、属性存取表达式等。
     运算符的优先级,这里就不说了。
     
七、函数
function关键字定义的大括号抱起来一段代码: function + 函数名 + (+ 参数 +) + { }抱起来的代码段; 
function fn(args ) {
     //函数要实现的功能代码;
}
也能够把函数赋值给一个变量:
var fn = function(args){
     //函数要实现的功能代码;
}
这两个是有区别的;后面再详细说明。
 
2、对象
 
一、对象字面量
var empty_object = {};
 
var  blog_name = {
     "first-name": "Skylor",
     "last-name": "min"
}
对象字面量是能够嵌套的;
 
 
二、检索
两种方法:
[]  通常用中括号的状况是,后面字符串是一个数字,或者是非合法标识符,或者是个变量等
.  通常用点的状况是,它是一个合法的JavaScript标识符且并不是保留字。
两个均可以用的时候,推荐用 . 点表示法,由于它更紧凑且可读性更好。
 
三、更新
 
对象中的值能够经过赋值语句来更新。若是有就更新,若是没有就扩充。
 
四、引用
 
对象经过引用来传递,它们永远不会被拷贝。这里有必要讲下拷贝,JavaScript的拷贝咱们分为浅拷贝和深拷贝。下面咱们来谈谈JavaScript中的浅拷贝以及深拷贝。
首先咱们来看看浅拷贝:
什么是浅拷贝,就是对于有嵌套对象的对象进行拷贝的时候,只拷贝了一层,对象里面的Array、object等嵌套的对象都不拷贝过来。简单的没有嵌套对象的对象,咱们用浅拷贝是没有问题的,对于复杂点的对象,就出现大问题了。下来咱们来看一个具体的例子:
var original = {
     num: 1,
     str: 'old string',
     obj: {
          obj_1: "old obj_1"
     },
     arr: [
         "array string",
           {
               arr_obj_1: "old arr obj 1"
          } 
     ]
}
看上面的这是一个比较复杂的对象,对象的里面包含了对象和数组。咱们来构建一个拷贝函数:
var extend = function(result, source){
     for(var key in source) {
         result[key] = source[key];
     }
     return result;
}
好,有了这个拷贝函数,下面咱们来测试下程序:
var copy_original = extend({}, original);
copy_original.str = "new String";
copy_original.obj.obj_1 = "new obj tring";
copy_original.arr[1].arr_obj_1 = "new Array obj String";
copy_original.arr[0] = "new Arrat string";
 
以上,咱们是否是只改变了咱们拷贝过来的copy_original的值啊,那么此时原来的对象ofiginal是否是应该仍是原来的值,咱们来运行看看就知道了{动手啊,必定要动手}。此时只有str和num保持不变了,其余的和咱们拷贝后的对象修改后的值同样了。
这样看来,若是咱们不想改变原来的对象,咱们须要对对象里面的对象和数组须要特殊待遇一下,固然咱们要给她们两特殊照顾,就得先认识她们,下面是认识她们这两个美女的函数:
 
var is = function (obj,type) {
 
  var toString = Object.prototype.toString;
 
  return (type === "null" && obj === null) ||
 
    (type === "undefined" && obj === undefined ) ||
 
    toString.call(obj).slice(8,-1) === type;
 
};
类型识别,用来认识对象和数组来着,有人要说了不是有typeof吗,typeof是不可靠的,由于Array会返回'object'。好,认识了她们,咱们再来处理,怎么样才能深拷贝呢,咱们的深拷贝函数应该拥有处理特殊处理值为对象或数组的键值对。 对于它们,程序会为目标对象先建立一个新对象与数组,而后再一层层拷下去。咱们能够看到它并无用hasOwnProperty,换言之,连原型中可遍历的属性都给它翻个底朝天。这样一层层的拷贝下去,因而便有了下面的(性能比较差,通常状况下线上项目谨慎使用):
 
 var deepCopy = function(result, source){
 
        for(var key in source) {
 
          var copy = source[key];
 
          if(source === copy) continue;  //如window.window === window,会陷入死循环,须要处理一下
 
          if( is(copy,"Object") || is(copy,"Array") ){
 
            result[key] = deepCopy(result[key] || {}, copy);
 
          } else {
 
            result[key] = copy;
 
          }
 
        }
 
        return result;
 
      };
 
能够用这个深拷贝函数来实践下上面相似的测试程序,得出结论,你便知晓了一切。关于JavaScript的浅拷贝和深拷贝网上的各式各样,但万变不离其宗,知道了为啥,你就能写出属于你本身的deepCopy function。
 
五、原型 prototype
 
每一个对象都连接到一个原型对象,而且它能够从中继承属性。全部经过对象字面量建立的对象都连接到Object.prototype 这个JavaScript中标准的对象上。
 
六、反射
 
检查对象并肯定对象有什么属性是一件很容易的事,只要试着去检索改属性并验证取得的值,typeof这个操做符,没错,是操做符,对肯定属性的类型颇有帮助。须要注意的是typeof,原型链中的任何属性也会产生一个值,有两个方法去处理这些不须要的属性:
     第一个是让你的程序检查并剔除函数值。
另外一个方法是使用hasOwnProperty 方法,若是对象拥有独有的属性,他将返回true,hasOwnProperty方法不会检查原型链。
ex.hasOwnProperty('number');   //true
ex.hasOwnProperty('constructor'); // false
 
七、枚举
for in 语句可用来遍历一个对象中的全部属性名,上面的深拷贝函数咱们就有用到了,该枚举过程将会列出全部的属性-----包括函数和一些你可能不关心的属性,全部有必要过滤掉那些你不想要的值。最为经常使用的过滤器是hasOwnProperty方法,以及typeof来排除函数:还有一点须要注意的是for in 语句对属性名出线的顺序是不肯定的,这一点须要注意下。
 
八、删除
delete运算符能够用来删除对象的属性,会益处对象中肯定包含的属性,它不会触及原型链中的任何对象。
有一点须要注意的是,你删除了对象的属性可能会让来自原型链中的属性浮现出来。
 
好,这节课咱们讲了JavaScript的基本语法和对象的一些详细内容,后面有些须要多多练习,修改代码调试。咱们下期见。
相关文章
相关标签/搜索