javascript和es5

javascript

ES5及以前

什么是javascript语言

  • 轻量级脚本语言
    不具备开发操作系统的能力,只用来编写控制其他大型应用程序(比如浏览器)的“脚本”

  • 嵌入式语言
    只用来做数学和逻辑运算,调用宿主环境(浏览器和node)的底层API

标识符

  • 第一个字符,可以是任意 Unicode 字母(包括英文字母和其他语言的字母),以及美元符号($)和下划线(_)
  • 后面字符加上Unicode 、$、_0-9

数据类型
数值、字符串、布尔值、undefined、null、对象(object、数组、函数)

确定类型方法
typeof(返回值是string)、instanceof、Object.prototype.toString

typeof Infinity// "number"
typeof '123' // "string"
typeof false // "boolean"
typeof undefined //"undefined" 
// 检查未声明的变量,而不报错
typeof a //"undefined"
function f() {}
typeof f //"function"
typeof {} [] null //"object"

null和undefined

  • null表示空的对象,转为数值为0,转为布尔为false
  • undefined表示未定义的原始值,转为数值为NaN,转为布尔为false

布尔值:!、相等不等运算符、比较大小运算符会转为boolean
转为false:undefined、null、false、0、NaN、空字符串;其余值视为true

数值
所有数字以64位浮点数形式存储

1===1.0 // true
0.1 + 0.2 === 0.3 //false

数值精度
1位符号位(0,1) 第2到12位指数位 13到64位小数位

精确表示整数:指数在(0,2047)之间,算上1+52位有效位,因此精度为-2^53 到2 ^53,超出则会出现错误;最多表示( 2的-1075 ,2的1024] ‘0或者Infinity’

(-1)^符号位 * 1.xx...xx * 2^指数部分
xx为2位时
举例 1.11*2^2表示7

科学计数法e或者E

  • 小数点前数字>21位或小数点后的0>5

进制表示
js内部会默认转为十进制

  • 十进制:没有前导0的数值或0加8,9
  • 八进制:0o或0O或(0加0-7的数字 es5严格模式、es6废弃
  • 十六进制:0x或0X的数值
  • 二进制:0b或0B的数值

特殊数值
+0、-0 :区别作为分母

-0 === +0 // true
(1 / +0) === (1 / -0) // false  +Infinity -Infinity

NaN:Not a Number,也是number类型
NaN不等于任何值包括自身

  • 字符串解析为数字
  • 数学函数运算结果
  • 0/0
5 - 'x' // NaN
注:5 + 'x' // 5x 当作字符串连接

Infinity:表示无穷,+Infinity和-Infinity(表示正负无穷)

  • Infinity与null计算时,null会转成0,等同于与0的计算
  • Infinity与undefined计算,返回的都是NaN
Infinity > NaN // false
-Infinity < NaN // false

0 * Infinity // NaN
Infinity - Infinity // NaN
Infinity / Infinity // NaN

parseInt:将字符串转为整数(返回值是NaN或10进制数)

  • 若不是字符串,转为字符串,去掉前缀空格
  • 依次转换,遇到不能转换时,则返回转好的部分;若第一个字符不能转化为数字或不是数值或字符串,返回NaN
  • 自动转为科学计算法的数字,会出现奇怪结果
  • 字符串以0x或0X开头,按十六进制数解析,其余(0、0b、0O)一律按十进制
  • 第二个参数(2,36)之间,表示被解析数的进制,超出则返回NaN,若参数是0、undefined、null、[]、{}直接忽略
parseInt('1546', 2) // 1 ,从最高位开始,只返回可以转换的数值
parseInt(0x11, 36) // 43
parseInt('') //NaN
// 等同于
parseInt('17', 36)

parseInt(011, 2) // NaN
// 等同于
parseInt(String(9), 2)

parseFloat:将一个字符串转为浮点数
与parseInt类似

isNaN:判断一个值位NaN

  • 会先转为数值,使用Number()函数
//判断NaN
typeof value === 'number' && isNaN(value)
value !== value

isFinite :判断是否为正常的数值

  • Infinity、NaN、undefined返回false,null返回true
  • 会先转为数值,使用Number()函数

数据类型转换
强制转换
Number() :任意类型值转化为数值

  • 比parseInt和parseFloat严格,只要一个字符不能转化为数值(2,8,16进制可以),则结果就为NaN
  • 过滤前后缀空格

原始类型值

Number(324) // 324
Number('324') // 324
Number('324abc') // NaN
Number('') // 0
Number(true) // 1
Number(false) // 0
Number(undefined) // NaN
Number(null) // 0

对象

  • 只有包含单个数值的数组,才返回对应值,否则返回NaN
Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([5]) // 5
Number([]) // 0

Number()求解流程

  • 调用对象自身的valueOf方法,返回原始类型值,则直接Number求解,否则进入下一步
  • 若valueOf方法返回的还是对象,则改为调用对象自身的toString方法,若tostring返回原始类型,则Number求解
  • 若tostring返回时对象,则报错

注:默认下对象的valueOf方法返回本身,调用toString返回对象的类型字符串
可自定义对象的valueOf和toString的方法

let f=()=>{}
f.valueOf() //[Function: f] ()=>{}
f={}
f.toString() //"[object Object]"
f=[[1],2,3]
f.toString() //"1,2,3"

String()

  • 数值:转为相应的字符串(还是会转成科学计数法)
  • 字符串不变、布尔值转为‘true’,‘false’,undefined和null转为字符串形式
  • 对象
String({a: 1}) // "[object Object]"
String([[1], 2, 3]) // "1,2,3"
String(()=>{}) //'()=>{}'

原理:先调用对象自身的toString,在调用源对象的valueOf,若最后返回对象则报错

Boolean

-Boolean(new Boolean(false)) // true

自动转换 (建议显式转换)

  • 不同数据类型的数据互相运算
  • 非布尔求布尔值(if,三元运算符)
  • 非数值类型的值使用一元运算法
    自动转换位字符串:+号一个元素是字符串
'5' + {} // "5[object Object]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"

自动转换位数值:正负号,- * /,Math方法

字符串

  • 单引号或双引号内部仍使用单双、或需要换行、转义则用反斜杠
  • 视为字符串数组,若索引不是数字或超出,则返回undefined;但无法改变单个字符;length属性返回长度,也无法改变
  • js引擎内部,所有字符用Unicode表示

Base64转码 :ASCLL0到31无法打印,以文本格式传递二进制格式

  • 为了不出现特殊字符,简化程序处理;转成0-9,A-Z,a-z,+/64个字符
  • btoa:转为base64编码
  • atob:base64编码转为原始值

对象
键名:字符串和symbol(es6);符合标识名或数字,否则必须要加引号

{ console.log(123) } // 123 解释为代码块
({ console.log(123) }) // 报错
eval('{foo: 123}') // 123 对字符串求值
eval('({foo: 123})') // {foo: 123}

delete 删除返回false:属性不得删除

//读取
obj[123]
obj[foo] //foo为变量 obj.foo 
//属性的查看
var obj = {
  key1: 1,
  key2: 2
};
Object.keys(obj);// ['key1', 'key2']
//属性的删除
delete obj.p//即使删除不存在的属性也返回true

in运算符:对象的属性(包含继承属性)是否存在

var obj = {a: 1, b: 2, c: 3};
'p' in obj // true
for (var i in obj) { // 遍历可遍历(enumerable);遍历自身和继承
  console.log('键名:', i);
  console.log('键值:', obj[i]);
}

with语句 :遍历操作同一个对象的多个属性
绑定当前作用域

var obj = {
  p1: 1,
  p2: 2,
};
with (obj) {
  p1 = 4;
  p2 = 5;
  p3=6;//创建全局变量,且赋值失败
}
obj.p3 //undefined 
p3 //6

with (obj) {
  console.log(x); 无法知道是obj.x 还是全局变量x
}

函数
声明方式:function命令、函数表达式()、Function构造函数

  • 重复声明 后面会覆盖前面
  • 函数与其他数据类型地位平等,又称为第一等公民
  • 函数提升:采用function命名,整个函数提升到代码头部,但函数表达式不会提升
  • name属性返回函数名,但函数表达式匿名取变量名,具名取具名;获取参数函数名
  • length属性返回 预期传入的参数个数(实现重载)
  • toString()方法返回函数的源码包括换行符和注释,若是原生,则返回‘native code’
function print(s) {
  console.log(s);
}
var print = function x(){
  console.log(typeof x); //只在函数内部有用;方便除错工具显示函数名,不再显示匿名函数
};
var add = new Function(
  'x',
  'y',
  'return x + y'
); //若只有一个参数,就是函数体
//name
var f3 = function myName() {};
f3.name // 'myName'

var myFunc = function () {};
function test(f) {
  console.log(f.name);
}
test(myFunc) // myFunc

Math.sqrt.toString()
// "function sqrt() { [native code] }"

函数作用域
全局作用域:变量在整个程序一直存在,任何地方都可读取
函数作用域:

  • 变量只在函数内部存在,函数内部定义的变量会覆盖同名全局变量
  • 存在变量提升,提升到函数体的头部
  • 绑定声明时所在的作用域
var a = 1;
var x = function () {
  console.log(a);
};
function f() {
  var a = 2;
  x();
}
f() // 1
  • 参数可省略,不可省略靠前参数
  • 原始类型是传值传递(不会影响原参数),若是对象则是传址传递
  • 同名参数,取最后出现的值

arguments对象:允许函数有不定数目的参数,函数内部获取所有参数

  • 可在运行时修改(严格模式’use strict’修改后不影响到实际的函数参数)
  • callee 属性返回原函数,严格模式禁用
Array.prototype.slice.call(arguments) //转为数组

闭包:能够读取函数内部变量的函数

  • 读取外层函数内部的变量
  • 变量记忆性,记住上一次调用的运算结果
function f1() {
  var n = 999;
  function f2() {  //f2是闭包
    console.log(n);
  }
  return f2;
}

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

function createIncrementor(start) {
  return function () {
    return start++;
  };
}
var inc = createIncrementor(5);
inc() // 5
inc() // 6
inc() // 7

数组:特殊的对象
length属性:可读可写,置为0可清空数组,若大于当前元素个数,空位补充(undefined)

var a=[];
a[2]=1; // [,,1] 不需要连续

var arr = [ 'a', 'b', 'c' ];
arr.length = 0;
arr // []

//超出范围,键名自动转为字符串
var arr = [];
arr[-1] = 'a';
arr[Math.pow(2, 32)] = 'b';
arr.length // 0
arr[-1] // "a"
arr[4294967296] // "b"

in运算法:某个位置是空位,返回false
跳过空位遍历:forEach、for…in、Object.keys
空位不等同于undefined

var arr = [];
arr[100] = 'a';
100 in arr // true
1 in arr // false

//for...in 不仅遍历数字键,还遍历非数字键
var a = [1, 2, 3];
a.foo = true;
for (var key in a) {
  console.log(key);
}

//delete 会形成空位,不影响length属性
delete a[1];
a[1] // undefined
a.length // 3

类数组对象
具有length属性,可转为数组(slice返回新数组)

var obj = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};
Array.prototype.slice.call(arguments) 

错误处理机制
Error构造函数,所有抛出的错误都是此对象的实例,并中断不再往下执行

var err = new Error('出错了');
err.message // "出错了"

原生错误类型

  • SyntaxError 对象:语法解析错误
  • ReferenceError 对象:不存在的变量或赋值给无法分配的对象
  • RangeError 对象:超出有效范围。数组范围为负数,Number超出范围,函数堆栈溢出
  • TypeError 对象:变量或参数不是预期类型时发生的错误
  • URIError 对象:encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()
  • EvalError:eval未被正确使用,被弃用

自定义错误

function UserError(message) {
  this.message = message || '默认信息';
  this.name = 'UserError';
}

UserError.prototype = new Error();
UserError.prototype.constructor = UserError;

throw:手动中断程序执行,抛出一个错误

throw new Error('x 必须为正数');
throw 42;

try…catch结构

  • catch会捕获try的错误,会继续执行代码,也可继续抛错;若无catch,则中断程序执行

finally:不管是否抛错,都执行的代码
return和throw可触发转入finally

var count = 0;
function countUp() {
  try {
    return count;
  } finally {
    count++;
  }
}
countUp()
// 0
count
// 1
function f() {
  try {
    console.log(0);
    throw 'bug';
  } catch(e) {
    console.log(1);
    return true; // 这句原本会延迟到 finally 代码块结束再执行
    console.log(2); // 不会运行
  } finally {
    console.log(3);
    return false; // 这句会覆盖掉前面那句 return
    console.log(4); // 不会运行
  }

  console.log(5); // 不会运行
}
//0 1 3 false

编程风格
JavaScript自动添加句末的分号
不建议使用with;语句后分号不要省略;不建议使用switchcase,使用对象结构

console
console对象的浏览器实现(chorme),打开F12,console面板

  • console方法都可自定义
  • console.debug只有打开verbose,否则不会显示
  • console.warn黄色标记 console.error红色标记
  • console.table 数组和对象展示成表格
  • console.count()该方法调用多少次
  • console.dir(展示对象)和console.dirxml(dom节点以目录树展示,若不是dom则与dir一致)
  • console.assert 不满足条件,则显示错误,不中断执行,第一个参数必须为false
  • console.time(),console.timeEnd()算出程序的时间,setTimeout无效
console.log('a', 'b', 'c')// a b c
console.log(' %s + %s = %s', 1, 1, 2) //s d i f o c
['log', 'info', 'warn', 'error'].forEach(function(method) {
  console[method] = console[method].bind(
    console,
    new Date().toISOString()
  );
});

console.log("出错了!");
// 2014-05-18T09:00.000Z 出错了!
console.assert(false, '判断条件不成立')// Assertion failed: 判断条件不成立

运算法
算术运算符

3 + 4 + '5' // "75"
var obj = { p: 1 };
obj + 2 // "[object Object]2"
//运算结果的正负号由第一个运算子的正负号决定
-1 % 2 // -1
1 % -2 // 1
//数值运算法跟Number函数类似
+true // 1
-[] // 0
+{} // NaN
//指数 右结合
// 相当于 2 ** (3 ** 2)
2 ** 3 ** 2

比较运算法
非相等运算法

  • 字符串比较:按unicode码点按位比较
  • 非字符串比较:原始类型,则转为数值再比较(出现NaN则false);对象先调用valueOf方法,如果返回的还是对象,再接着调用toString方法
let t=[300]>'4'; //false
let t=[300]>4;  //true

== 和 ===

===:若不是同类型,则返回false,再比较(复合类型,比较是否指向同一地址)

==:会将它们转换成同一个类型,再用 ===比较

  • 原始类型会转成数值再比较
  • 对象类型(包括数组和函数)先调用valueOf(),再调用toString()
{} === {} // false
[] === [] // false
(function () {} === function () {}) // false
//null与undefined 与其他值都不相等
undefined == null // true

&&:如果第一个运算子的布尔值为true,则返回第二个运算子的(注意是值,不是布尔值);如果第一个运算子的布尔值为false,则直接返回第一个运算子的值,且不再对第二个运算子求值
||:如果第一个运算子的布尔值为true,则返回第一个运算子的值,且不再对第二个运算子求值;如果第一个运算子的布尔值为false,则返回第二个运算子的值

void运算法:浏览器的书签工具,插入代码防止网页跳转

  • 执行一个表达式,然后不返回任何值
<a href="http://example.com" onclick="f(); return false;">点击</a>
<a href="javascript: void(f())">文字</a>

逗号运算符 返回最后一个表达式的值

右结合:**,?,=

标准库
Obejct对象

value === Object(value) //判断是否为对象
var obj = new Object()//var obj = {} 等价

Object静态方法

  • Object.keys:对象自身、可枚举的属性
  • Object.getOwnPropertyNames:对象自身的所有属性

Object实例方法:定义再原型上的方法

  • Object.prototype.valueOf():默认情况下与对象本身一样,除非修改valueof方法
  • Object.prototype.toString():返回
  • Object.prototype.toString.call(value):可判断类型
  • Object.prototype.toLocaleString():与tostring类似,预留给地域翻译
  • Object.prototype.hasOwnProperty():自身是否具有某属性(不算继承属性)
var obj = new Object();
obj.valueOf() === obj // true

var obj = new Object();
obj.valueOf = function () { //修改valueOf方法
  return 2;
};

1 + obj // 3
var o1 = new Object();
o1.toString() // "[object Object]"

属性描述对象

{
  value: 123, //属性值
  writable: false, //属性值可写性
  enumerable: true, //可枚举性 (遍历)
  configurable: false, // 属性对象可写性,false时,value、writable、enumerable和configurable不能被修改
  get: undefined,
  set: undefined
}
  • Object.getOwnPropertyDescriptor(obj,’p‘):获取自身属性的描述对象
var obj = { p: 'a' };

Object.getOwnPropertyDescriptor(obj, 'p')
// Object { value: "a",
//   writable: true,
//   enumerable: true,
//   configurable: true
// }
  • Object.defineProperty():定义或修改一个属性,返回修改后的对象
  • Object.defineProperties():定义或修改多个属性,writable、configurable、enumerable默认值都为false
var obj = Object.defineProperty({}, 'p', {
  value: 123,
  writable: false,
  enumerable: true,
  configurable: false
});
obj.p // 123
obj.p = 246;
obj.p // 123

//修改多个属性
var obj = Object.defineProperties({}, {
  p1: { value: 123, enumerable: true },
  p2: { value: 'abc', enumerable: true },
  p3: { get: function () { return this.p1 + this.p2 },
    enumerable:true,
    configurable:true
  }
});
  • Object.prototype.propertyIsEnumerable():某属性可枚举,若是继承返回false

get set

//configurable和enumerable都为true
var obj = {
  get p() {
    return 'getter';
  },
  set p(value) {
    console.log('setter: ' + value);
  }
};

控制对象状态

  • Object.preventExtensions(obj):使得一个对象无法再添加新的属性
  • Object.isExtensible():检查是否使用了Object.preventExtensions方法,检查是否可以为一个对象添加属性
  • Object.seal(obj):对象既无法添加新属性,也无法删除旧属性
  • Object.isSealed():是否使用了Object.seal
  • Object.freeze():无法添加新属性、无法删除旧属性、也无法改变属性的值,使得这个对象实际上变成了常量
  • Object.isFrozen():是否使用Object.freeze()

可以通过改变原型对象,来为对象增加属性;若属性值是对象,不能冻结对象本身的内容

Array

  • Array.isArray(arr)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值