Javascript语法速查

如果只是声明变量而没有赋值,则该变量的值是undefinedundefined是一个 JavaScript 关键字,表示“无定义”。

var a;
a // undefined

变量提升:JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。

console.log(a);
var a = 1;


//等价于

var a;
console.log(a);
a = 1;

//最后的结果是undefined,表示变量a已声明,但还未赋值。

标签(label)

JavaScript 语言允许,语句的前面有标签(label),相当于定位符,用于跳转到程序的任意位置,标签的格式如下。

标签可以是任意的标识符,但不能是保留字,语句部分可以是任意语句。

标签通常与break语句和continue语句配合使用,跳出特定的循环。

top:  
  for (var i = 0; i < 3; i++){   for (var j = 0; j < 3; j++){   if (i === 1 && j === 1) break top;   console.log('i=' + i + ', j=' + j);   }   } // i=0, j=0 // i=0, j=1 // i=0, j=2 // i=1, j=0
continue语句也可以与标签配合使用。

 

上面代码为一个双重循环区块,break命令后面加上了top标签(注意,top不用加引号),满足条件时,直接跳出双层循环。如果break语句后面不使用标签,则只能跳出内层循环,进入下一次的外层循环。

 

continue语句也可以与标签配合使用。

top:
  for (var i = 0; i < 3; i++){
    for (var j = 0; j < 3; j++){
      if (i === 1 && j === 1) continue top;
      console.log('i=' + i + ', j=' + j);
    }
  }

// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
// i=2, j=0
// i=2, j=1
// i=2, j=2

上面代码中,continue命令后面有一个标签名,满足条件时,会跳过当前循环,直接进入下一轮外层循环。如果continue语句后面不使用标签,则只能进入下一轮的内层循环。

数据类型

1.概述

  • 数值(number):整数和小数(比如13.14
  • 字符串(string):文本(比如Hello World)。
  • 布尔值(boolean):表示真伪的两个特殊值,即true(真)和false(假)
  • undefined:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值
  • null:表示空值,即此处的值为空。
  • 对象(object):各种值组成的集合。
  • Symbol 

对象是最复杂的数据类型,又可以分成三个子类型。

  • 狭义的对象(object)
  • 数组(array)
  • 函数(function)

2.typeof 运算符

JavaScript 有三种方法,可以确定一个值到底是什么类型。

  • typeof运算符
  • instanceof运算符
  • Object.prototype.toString方法

3.null 和 undefined

对于nullundefined,大致可以像下面这样理解。

null表示空值,即该处的值现在为空。调用函数时,某个参数未设置任何值,这时就可以传入null,表示该参数为空。比如,某个函数接受引擎抛出的错误作为参数,如果运行过程中未出错,那么这个参数就会传入null,表示未发生错误。

undefined表示“未定义”,下面是返回undefined的典型场景。

// 变量声明了,但没有赋值
var i;
i // undefined

// 调用函数时,应该提供的参数没有提供,该参数等于 undefined
function f(x) {
  return x;
}
f() // undefined

// 对象没有赋值的属性
var  o = new Object();
o.p // undefined

// 函数没有返回值时,默认返回 undefined
function f() {}
f() // undefined

 

4.布尔值

如果 JavaScript 预期某个位置应该是布尔值,会将该位置上现有的值自动转为布尔值。转换规则是除了下面六个值被转为false,其他值都视为true

  • undefined
  • null
  • false
  • 0
  • NaN
  • ""''(空字符串)

5.数值

parseInt()

(1)基本用法

parseInt方法用于将字符串转为整数。

parseInt('123') // 123


parseInt('   81') // 81

//如果字符串头部有空格,空格会被自动去除。

如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN

 

parseFloat()

parseFloat方法用于将一个字符串转为浮点数。

isNaN()

isNaN方法可以用来判断一个值是否为NaN

isFinite()

isFinite方法返回一个布尔值,表示某个值是否为正常的数值。

isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false
isFinite(-1) // true

除了Infinity-InfinityNaN这三个值会返回falseisFinite对于其他的数值都会返回true

字符串

JavaScript 使用 Unicode 字符集。JavaScript 引擎内部,所有字符都用 Unicode 表示。

Base64 转码

有时,文本里面包含一些不可打印的符号,比如 ASCII 码0到31的符号都无法打印出来,这时可以使用 Base64 编码,将它们转成可以打印的字符。另一个场景是,有时需要以文本格式传递二进制数据,那么也可以使用 Base64 编码。

所谓 Base64 就是一种编码方法,可以将任意值转成 0~9、A~Z、a-z、+/这64个字符组成的可打印字符。使用它的主要目的,不是为了加密,而是为了不出现特殊字符,简化程序的处理。

JavaScript 原生提供两个 Base64 相关的方法。

  • btoa():任意值转为 Base64 编码
  • atob():Base64 编码转为原来的值
var string = 'Hello World!';
btoa(string) // "SGVsbG8gV29ybGQh"
atob('SGVsbG8gV29ybGQh') // "Hello World!"

 

要将非 ASCII 码字符转为 Base64 编码,必须中间插入一个转码环节,再使用这两个方法。

function b64Encode(str) {
  return btoa(encodeURIComponent(str));
}

function b64Decode(str) {
  return decodeURIComponent(atob(str));
}

b64Encode('你好') // "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"

 

对象

注意,数值键名不能使用点运算符(因为会被当成小数点),只能使用方括号运算符。

var obj = {
  123: 'hello world'
};

obj.123 // 报错
obj[123] // "hello world"

 

查看所有属性

查看一个对象本身的所有属性,可以使用Object.keys方法。

var obj = {
  key1: 1,
  key2: 2
};

Object.keys(obj);
// ['key1', 'key2']

 

delete 命令

delete命令用于删除对象的属性,删除成功后返回true

 

var obj = { p: 1 };
Object.keys(obj) // ["p"]

delete obj.p // true
obj.p // undefined
Object.keys(obj) // []

 

for…in 循环

for...in循环用来遍历一个对象的全部属性。

var obj = {a: 1, b: 2, c: 3};

for (var i in obj) {
  console.log(obj[i]);
}
// 1
// 2
// 3
var obj = {
  x: 1,
  y: 2
};
var props = [];
var i = 0;

for (var p in obj) {
  props[i++] = p
}

props // ['x', 'y']

for...in循环有两个使用注意点。

  • 它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性。
  • 它不仅遍历对象自身的属性,还遍历继承的属性。

函数

第一等公民

JavaScript 语言将函数看作一种值,与其它值(数值、字符串、布尔值等等)地位相同。凡是可以使用值的地方,就能使用函数。比如,可以把函数赋值给变量和对象的属性,也可以当作参数传入其他函数,或者作为函数的结果返回。函数只是一个可以执行的值,此外并无特殊之处。

由于函数与其他数据类型地位平等,所以在 JavaScript 语言中又称函数为第一等公民。

 

函数本身的作用域

函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关。

var a = 1;
var x = function () {
  console.log(a);
};

function f() {
  var a = 2;
  x();
}

f() // 1

同样的,函数体内部声明的函数,作用域绑定函数体内部。

 

function foo() {
  var x = 1;
  function bar() {
    console.log(x);
  }
  return bar;
}

var x = 2;
var f = foo();
f() // 1

如果函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference)。也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。

 

var obj = { p: 1 };

function f(o) {
  o.p = 2;
}
f(obj);

obj.p // 2

上面代码中,传入函数f的是参数对象obj的地址。因此,在函数内部修改obj的属性p,会影响到原始值。

注意,如果函数内部修改的,不是参数对象的某个属性,而是替换掉整个参数,这时不会影响到原始值。

 

 

var obj = [1, 2, 3];

function f(o) {
  o = [2, 3, 4];
}
f(obj);

obj // [1, 2, 3]

上面代码中,在函数f内部,参数对象obj被整个替换成另一个值。这时不会影响到原始值。这是因为,形式参数(o)的值实际是参数obj的地址,重新对o赋值导致o指向另一个地址,保存在原地址上的值当然不受影响。

 

arguments 对象

(1)定义

由于 JavaScript 允许函数有不定数目的参数,所以需要一种机制,可以在函数体内部读取所有参数。这就是arguments对象的由来。

arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,arguments[1]就是第二个参数,以此类推。这个对象只有在函数体内部,才可以使用。

 

闭包

闭包(closure)是 Javascript 语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。

理解闭包,首先必须理解变量作用域。前面提到,JavaScript 有两种作用域:全局作用域和函数作用域。函数内部可以直接读取全局变量。

 

function f1() {
  var n = 999;
  function f2() {
    console.log(n);
  }
  return f2;
}

var result = f1();
result(); // 999

上面代码中,函数f1的返回值就是函数f2,由于f2可以读取f1的内部变量,所以就可以在外部获得f1的内部变量了。

闭包就是函数f2,即能够读取其他函数内部变量的函数。由于在 JavaScript 语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。闭包最大的特点,就是它可以“记住”诞生的环境,比如f2记住了它诞生的环境f1,所以从f2可以得到f1的内部变量。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

 

闭包的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。请看下面的例子,闭包使得内部变量记住上一次调用时的运算结果。

function createIncrementor(start) {
  return function () {
    return start++;
  };
}

var inc = createIncrementor(5);

inc() // 5
inc() // 6
inc() // 7

上面代码中,start是函数createIncrementor的内部变量。通过闭包,start的状态被保留了,每一次调用都是在上一次调用的基础上进行计算。从中可以看到,闭包inc使得函数createIncrementor的内部环境,一直存在。所以,闭包可以看作是函数内部作用域的一个接口。

为什么会这样呢?原因就在于inc始终在内存中,而inc的存在依赖于createIncrementor,因此也始终在内存中,不会在调用结束后,被垃圾回收机制回收。

闭包的另一个用处,是封装对象的私有属性和私有方法。

function Person(name) {
  var _age;
  function setAge(n) {
    _age = n;
  }
  function getAge() {
    return _age;
  }

  return {
    name: name,
    getAge: getAge,
    setAge: setAge
  };
}

var p1 = Person('张三');
p1.setAge(25);
p1.getAge() // 25

上面代码中,函数Person的内部变量_age,通过闭包getAgesetAge,变成了返回对象p1的私有变量。

注意,外层函数每次运行,都会生成一个新的闭包,而这个闭包又会保留外层函数的内部变量,所以内存消耗很大。因此不能滥用闭包,否则会造成网页的性能问题。

 

eval 命令

eval命令的作用是,将字符串当作语句执行。

通常情况下,eval最常见的场合是解析 JSON 数据字符串,不过正确的做法应该是使用浏览器提供的JSON.parse方法。

JavaScript 引擎内部,eval实际上是一个引用,默认调用一个内部方法。这使得eval的使用分成两种情况,一种是像上面这样的调用eval(expression),这叫做“直接使用”,这种情况下eval的作用域就是当前作用域。除此之外的调用方法,都叫“间接调用”,此时eval的作用域总是全局作用域。

 

var a = 1;

function f() {
  var a = 2;
  var e = eval;
  e('console.log(a)');
}

f() // 1

异或运算

异或运算(^)在两个二进制位不同时返回1,相同时返回0

“异或运算”有一个特殊运用,连续对两个数ab进行三次异或运算,a^=b; b^=a; a^=b;,可以互换它们的值。这意味着,使用“异或运算”可以在不引入临时变量的前提下,互换两个变量的值。

var a = 10;
var b = 99;

a ^= b, b ^= a, a ^= b;

a // 99
b // 10

左移运算符

左移运算符(<<)表示将一个数的二进制值向左移动指定的位数,尾部补0,即乘以2的指定次方(最高位即符号位不参与移动)。

 

// 4 的二进制形式为100,
// 左移一位为1000(即十进制的8)
// 相当于乘以2的1次方
4 << 1
// 8

-4 << 1
// -8

 

右移运算符

右移运算符(>>)表示将一个数的二进制值向右移动指定的位数,头部补0,即除以2的指定次方(最高位即符号位不参与移动)。

 

4 >> 1
// 2
/*
// 因为4的二进制形式为 00000000000000000000000000000100,
// 右移一位得到 00000000000000000000000000000010,
// 即为十进制的2
*/

-4 >> 1
// -2
/*
// 因为-4的二进制形式为 11111111111111111111111111111100,
// 右移一位,头部补1,得到 11111111111111111111111111111110,
// 即为十进制的-2
*/

 

 

转载于:https://www.cnblogs.com/hznu-ksco/p/8298711.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值