JS必知必会与我的盲点易混淆点

在1995 年 Netscape 一位名为 Brendan Eich 的工程师创造了 JavaScript,随后在 1996 年初,JavaScript 首先被应用于 Netscape 2 浏览器上。最初的 JavaScript 名为 LiveScript,后来因为 Sun Microsystem 的 Java 语言的兴起和广泛使用,Netscape 出于宣传和推广的考虑,将它的名字从最初的 LiveScript 更改为 JavaScript——尽管两者之间并没有什么共同点。这便是之后混淆产生的根源。

几个月后,Microsoft 随着 IE 3 推出了一个与之基本兼容的语言 JScript。又几个月后,Netscape 将 JavaScript 提交至 Ecma International(一个欧洲标准化组织), ECMAScript 标准第一版便在 1997 年诞生了,随后在 1999 年以 ECMAScript 第三版的形式进行了更新,从那之后这个标准没有发生过大的改动。由于委员会在语言特性的讨论上发生分歧,ECMAScript 第四版尚未推出便被废除,但随后于 2009 年 12 月发布的 ECMAScript 第五版引入了第四版草案加入的许多特性。第六版标准已经于2015年六月发布。

类型

JavaScript中的类型包括:

  • Number, 数字
  • String
  • Boolean
  • Function, 函数
  • Symbol, 符号 第六版新增的
  • Object, 对象

    • Function,函数
    • Array, 数组
    • Date, 日期
    • RegExp, 正则
  • Null 空

  • undefine 未定义

Number

根据语言规范,JavaScript采用“IEEE 754 标准定义的双精度64位格式”(”double-precision 64-bit format IEEE 754 values”)表示数字。因此JS不去整点数和浮点数值,他们均用浮点数表示。

JS支持标准的算术运算。同JAVA一样,也有一个内置的数学对象Math,用来处理高级数学函数和数学常量。

Math.sin(3.5);
var d = Math.PI * (r + r);

我们也可以使用内置函数parseInt()将字符串型数字转换为整型。他有两个参数,第二个表示进制。如果入参一0开头,且不传第二个参数。表示传入的为8进制。入参以0X开头,同理。

parseInt("010");  //  8
parseInt("0x10"); // 16
  • 如果传入的不是数字,就会返回一个特殊值NaN.即Not a Number
  • 内置函数isNaN(NaN)==true,用来判断是否是数字。
  • JS还有两个特殊值。Infinity,正无穷和-Infinity,负无穷。
  • 内置函数isFinite() 用来判断一个数是否是有穷数。

字符串

JavaScript 中的字符串是一串Unicode 字符序列。这对于那些需要和多语种网页打交道的开发者来说是个好消息。更准确地说,它们是一串UTF-16编码单元的序列,每一个编码单元由一个 16 位二进制数表示。每一个Unicode字符由一个或两个编码单元来表示。

如果想表示一个单独的字符,只需使用长度为 1 的字符串。

通过访问字符串的 长度(编码单元的个数)属性可以得到它的长度。

"hello".length; // 5

这是我们第一次碰到 JavaScript 对象。我们有没有提过你可以像 objects 一样使用字符串?是的,字符串也有methods(方法)能让你操作字符串和获取字符串的信息。

"hello".charAt(0); // "h"
"hello, world".replace("hello", "goodbye"); // "goodbye, world"
"hello".toUpperCase(); // "HELLO"

其他类型

JavaScript 中 null 和 undefined 是不同的,前者表示一个空值(non-value),必须使用null关键字才能访问,后者是“undefined(未定义)”类型的对象,表示一个未初始化的值,也就是还没有被分配的值。

JavaScript 包含布尔类型,这个类型的变量有两个可能的值,分别是 true 和 false(两者都是关键字)。根据具体需要,JavaScript 按照如下规则将变量转换成布尔类型:

  • false、0、空字符串(“”)、NaN、null 和 undefined被转换为 false
  • 所有其他值被转换为 true

变量

在JS中声名一个新变量使用关键字var,如果未初始化则默认值为undefined。

与JAVA不同,JS语句块(Blocks)是没有作用域的,只有函数有作用域。所以如果在一个函数或者if语句块中使用var声名了一个变量,那他的作用就是这个函数或者if语句块中。
但是从ES6 开始,允许使用let 和const块作用域的变量。

let  l1= 100;
var  v2 = 200;   
if(true)  {
    let  l1 = 200;
    var  v2 = 300;
    console.log(l1);  //200
    console.log(v2);  //300
}
    console.log(l1);  //100
    console.log(v2);  //300 

运算符

基本与Java运算符类似,也支持位运算

需要注意的是== 与 ===, 前者在比较是有类型自适应的功能,即会对类型自动进行相应转换。而后者不会。同理也有!= 和 !==

123 == "123" // true
1 == true; // true

--------------------------------------
1 === true; //false
123 === "123"; // false

控制结构

同JAVA一样,if,for,while,do..while,也支持三目运算符,switch分支语句(其中的判断条件都是===)。

对象

JS中创建对象的方式有两种。
1. var obj = new Object();
2. var obj = {[属性名称:属性值],[],[],…};这种为常用。

var obj = {
    name: "Carrot",
    "for": "Max",
    details: {
        color: "orange",
        size: 12
    }
}

而这些属性可以通过链式访问。这两种访问是一样的

obj.details.color; // orange
obj["details"]["size"]; // 12

数组

JS的一个数组对象中可以放不同类型的变量。
数组可以通过以下方法创建:
1. var arr = new Array();
arr[0] = “a1”; arr[2] = “a2”;
2. var arr = {“a1”,”a2”,”a3”} ;

需要注意的是arr.length并不总等于他的元素个数。而是等于最大索引值+1.

var arr = {"a1","a2","a3"} 
arr.length;   //3
arr[100] = a100;
arr.length;   //101

如果视图访问一个不存在的数组索引,得到就是undefined

typeof(arr[90]);   //undefined 

数组的遍历要注意的是如果使用for…in循环,当有人向Array.prototype添加了新的属性时,也会被遍历出来。

for(var i in arr) {
    //TODO: 
}

Array也自带了许多方法,详情可查看

方法名称描述
a.toString()返回一个包含数组中所有元素的字符串,每个元素通过逗号分隔。
a.toLocaleString()根据宿主环境的区域设置,返回一个包含数组中所有元素的字符串,每个元素通过逗号分隔。
a.join(sep)返回一个包含数组中所有元素的字符串,每个元素通过指定的 sep 分隔。
a.pop()删除并返回数组中的最后一个元素。
a.push(item1, …, itemN)将 item1、item2、……、itemN 追加至数组 a。
a.reverse()数组逆序(会更改原数组 a)。
a.shift()删除并返回数组中第一个元素。
a.slice(start, end)返回子数组,以 a[start] 开头,以 a[end] 前一个元素结尾。
a.sort([cmpfn])依据 cmpfn 返回的结果进行排序,如果未指定比较函数则按字符顺序比较(即使元素是数字)。

函数

学习JS最重要的就是理解对象和函数这两个部分,一个简单的函数例子:

function add(x, y) {
    var total = x + y;
    return total;
}

JavaScripte中的函数也是非常灵活的,与java相比,它不需要特别定义返回值,如果没有return,方法则会返回undefined。方法的参数也就是作指示作用,在调用时也可不传方法的形参,如果这些参数之前为被初始化,则默认传的也是undefined。

add(); // NaN 
// 不能在 undefined 对象上进行加法操作

而且你也可以传入参数多于方法的参数。只不过后面的会被忽略掉。
或许看上去有点废。实际上,JS中有个内部对象arguments,他可以说是数组的一个对象,方法的所有参数都会被存到这个对象中。我们来重新写个方法,可以计算所有传入参数的平均数。
当我们不知道参数有多少时,就可以使用这个对象了,如果java里的可变参数。”…”

function avg(){
    var sum = 0;
    for(var i; i< arguments.length; i++){
        sum += arguments[i];
    }
    return sum/arguments.length;
}
avg(1,2,3,4,5);   //3
  • 但是如果我们需要传入一个数组来计算他的平均值呢,是不是要重新写个方法?
    这里可以不用!我们知道了JS中函数也是对象,因此所有的函数都有个叫appley() 的方法。
    所以我们可以这样,第二个参数传个他一个数组,他会被当成avg()方法的参数看待。
avg.apply(null,[1, 2, 3, 4, 5]); //3

我们还可以创建匿名函数,这种方法的使用同上面的定义是一样的。

var avg = function(){
    var sum = 0;
    for(var i=0; i < arguments.length; i++){
        sum += arguments[i];    
    }
    return sum/arguments.length;
};

JS也支持函数的递归。但是开发中一般不建议使用递归,一个不小心就会内存溢出。
但是也某些时候也是非常实用的。例如在处理树形结构时。。

function countChars(elm) {
    if (elm.nodeType == 3) { // 文本节点
        return elm.nodeValue.length;
    }
    var count = 0;
    for (var i = 0, child; child = elm.childNodes[i]; i++) {
        count += countChars(child);
    }
    return count;
}

JS的函数就是他们的对象,同其他对象一样,可以添加或更改他们的属性。

自定义对象

自定义对象的方式有很多种,每种都有他的一些利弊端。我们以创建Animal对象为例,如下:

function Animal(name, talk){
    this.name = name;
        this.talk = talk;
    this.showName = function(){
        return this.name;
    }
    this.talkWa = function(){
        return this.name + "" + this.talk;
    }
}

这样创建对象是使用了this关键字,表示当前调用函数时的对象。如果没有该函数没有指定对象调用,那么this指的就是全局对象(global object)。我们基本上不适用这种方法自定义对象。我们可以使用new关键字获取新的对象。
但是有个问题是,每次使用new创建一个新的对象时,里面的函数对象也会被多次创建。而实际上每个Animal对象调用的函数可以是同一个。所以这些函数代码如果可以共享就好了。
有两种方法:

  • 将方法声明在外面,当作属性赋值给Animal
function aniTalkWay (){
        return this.name + "" + this.talk;
}
function aniShowName = function(){
        return this.name;
    }

function Animal(name, talk){
    this.name = name;
    this.talk = talk;
    this.talkWay = aniTalkWay ;
    this.showName = aniShowName ;
}
  • 还有一种需要使用到prototype关键字。
function Animal(name, talk){
    this.name = name;
    this.talk = talk;
}
Animal.prototype.aniTalkWay = function(){
    return this.name + "  " + this.talk;
};
Animal.prototype.aniShowName = function(){
    return this.name 
};

Animal.prototype中的属性为所有Animal的实例对象所共享。当我们访问Animal的属性时,解释器都会先到这个prototype的属性中寻找。
你甚至可以在运行时给已存在的对象添加新的方法。

var ani  = new Animal("BILL","mie");
ani.changeName();   //"Uncaught TypeError: undefined is not a function"
Animal.prototype.changename = function(){
    return this.name.toLocaleLowerCase()
};
ani.changeName();   //bill
  • 我们甚至还可以给js原始对象的prototype中添加属性。
var s = "Simon";
s.reversed(); // TypeError on line 1: s.reversed is not a function

String.prototype.reversed = function() {
    var r = "";
    for (var i = this.length - 1; i >= 0; i--) {
        r += this[i];
    }
    return r;
}
s.reversed(); // nomiS

学习资料来自:重新介绍 JavaScript

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值