JavaScript(一)
JavaScript(一)
基于《JavaScript高级程序设计》
基础语法与c类似,面向对象跟Java类似(我瞎说的
组成:
- 核心(ECMAScript)
- 文档对象模型(DOM)
- 浏览器对象模型(BOM)
基本语法
typeof
(操作符) 检测给定变量的数据类型eg:
1
2typeof xxx
typeof(xxx) // 两种格式都可var声明变量而未加以初始化时,变量的值为
undefined
null
空对象指针undefined
派生于其中,1
null == undefined // 结果为true
Boolean
类型, 通过Boolean()
函数可将一些数据类型转化。1
Boolean(NaN) == false
Object类型
:是所有实例的基础1
2var o = new Object()
var o = new Object // 不传参的情况下可省无符号右移
>>>
- 相等不相等:先转换操作数再比较
1
"55"==55 // true
- 全等不全等 === / !== :直接比较
奇怪的操作:
1
var num=(5,6,7,8) //不报错,num被赋值为8
for-in
:枚举对象的属性1
2
3
4for(var p in window){
// 每一次循环都会将window的一个属性值赋给p
document.write(p);
}label
:标记 与continue和break连用with
将代码的作用域设置到一个特定的对象中,个人感觉跟kotlin的apply语法糖类似
eg:1
2
3
4
5
6
7
8
9
10
11var qs = location.search.substring(1);
var hostName = location.hostname;
var url = location.href;
// 可写为
with(location){
var qs = search.substring(1);
var hostName = hostname;
var url = href;
}function
关键字声明函数eg:
1
2
3function FunctionName(arg0, arg1, ... argN){
statement here;
}比较有趣的是命名的参数不是必需的,而是用来提供便利的,ECS5中函数的参数是一个
arguments
对象,它与数组类似但不是数组的实例,可以通过arguments[0], arguments[1]...
来调用命名参数,arguments.length
获取参数的个数即’数组’长度(由命名参数的个数决定)。在非严格模式下,修改命名参数的值会修改arguments
对应的值,但注意它们的内存空间实际是相互独立的。 (我一开始还想的是命名参数会不会是arguments对应元素的指针。没有重载
变量、作用域、内存问题
- 基本类型值
- 复制:直接产生副本
- 引用类型值
- 复制:产生的是指针的副本,即新的值是对旧对象的引用
- 按值传递
- 注意函数传值为对象类型时,产生了复制,从而可以修改外部对象的属性值
检测引用类型值
instanceof
语法:
1
2// 变量是指定类型吗? 返回结果
res = variable instanceof constructor ;执行环境:都包含一个与之关联的变量对象。在一个环境中执行时,会创建变量对象的一个作用域链。其前端是所在环境定义的变量对象,然后逐级浮出,末端为全局变量。
延长作用域链
- with 语句
- try-catch块 :块外部也可访问内部错误对象
没有块作用域
即if/for等声明的变量外部也可访问
垃圾清除
由执行环境负责管理代码执行过程中使用的内存。
标记清除(周期性执行):
i. 标记进入环境的变量
ii. 去除环境中的变量以及被环境中变量引用的变量(嵌套)的标记
iii. 还有标记的变量被视为可删除的变量
记得golang用的是三色标记法。
引用计数
基于引用次数,用的很少,存在“循环引用”的问题。
有时候可能得手动解除引用
引用类型
对象是某个特定引用类型的实例
不同于类
创建对象
new Object()
对象字面量
1
2
3
4
5
6var person = {
name : "xxxx",
age : xx
};
var person = {}; //等价于new Object()
Array类型:每一项可以保存任意类型的数据,大小动态调整
1
2
3
4
5
6var array = new Array();
var array = new Array(10); // 可以指定length
var array = new Array("red", "yellow"); //可直接初始化
var array = Array{}; // 可省略 new
var array = []; // 数组字面量表示
var array = ["red", "yellow"];通过索引进行访问
索引超过数组现有项数,则数组长度会增长,新项添加到数组末尾
array.length 返回长度 可以通过该属性来对数组末尾添加值
eg:
1
array[array.length] = "new_Items";
检测方法:
Array.isArray(array)
继承了
toString()/toLocaleString()/valueOf()
方法array.join("指定分隔符")
栈/队列方法:
eg:
1
2
3
4
5
6
7var count = array.push(item1, item2); // 返回操作完成后数组的长度
var item = array.pop();
item = array.shift(); // 弹出队首项
item = array.unshift(new_item); // 队首添加新项,与pop结合实现逆向队列操作
排序方法:
eg:
1
2array.reverse(); //逆向排
array.sort(compare); // 默认升序,可接收一个自定义比较函数操作方法:
eg:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// concat()
var colors = ["red", "blue", "green"];
var colors2 = colors.concat("yellow", ["black", "brown"]);
// slice() 通过索引创建
var colors3 = colors.slice(0, 2) // 左闭右开
// splice()
// 删除指定项
splice(0, 2) // 第一个参数为指定位置,第二个是需要删除的项数
// 插入
splice(1, 0, item1, item2, ...) //指定删除项数为0
// 替换
splice(1, 1, new_item) // 添加数与删除数不需要相等位置方法:
indexOf() / lastIndexOf()
都接受两个参数,第一个是查找的项,第二个是查找的起始位置,返回值为在数组的索引。迭代方法:对每一项执行给定函数
every() filter() forEach() map() some()
归并方法:
reduce() reduceRight()
后者只不过是反过来而已,接收的参数为一个函数,其有四个参数,前一个值,当前值,项的索引,数组对象。eg: 累加求数组和
1
2
3
4var values = [1,2,3,4,5]
var sum = values.reduce(function(prev, cur, index, array){
return prev + cur
}); //15
Date()类型,用的时候查
RegExp类型 : 支持正则表达式
基本格式:
var exp = / pattern / flags
pattern : 正则表达式
flags : 每个正则表达式可带的一个或多个表达式
- g 全局模式
- i 不区分大小写
- m 多行模式
eg:
1
2
3
4
5
6
//1. 正则表达式字面量
var pattern1 = /[bc]at/i;
//2. RegExp构造函数
var pattern2 = new RegExp("[bc]at", "i") // 个人觉得这个可读性强些方法:
i.
exec()
接收一个参数为待匹配的字符串,返回包含一个Array的实例或者null该实例包含index
和input
两个额外属性,前者表示匹配项的索引,后者表示应用的正则表达式字符串。数组的第一项相当于模式匹配的第一部分,后续项数由捕获组确定。ii.
test()
接收一个参数,返回输入文本与模式是否匹配
Function类型:每个函数都是Function类型的实例
函数名仅仅是指向函数的指针
函数表达式实例:
eg:
1
2
3var sum = function(num1, num2){
return num1 + num2;
};解析器会率先解析函数声明,javaScript引擎会声明函数并将其放到源代码树的顶部,所以以下例子是正确的:
eg:1
2
3
4alert(sum(10,10)); // 20
function sum(num1, num2){
return num1 + num2;
}但是函数表达式不行,你可以理解为使用了未声明的变量
去掉函数名后面的那对圆括号,意味着访问函数的指针但不执行函数
函数内部属性:
arguments
之前介绍过大部分。其有一个属性callee
为指针类型指向拥有这个arguments对象的函数this
引用函数执行的环境对象caller
调用当前函数的函数的引用(即存在嵌套调用)length
函数希望接收的参数的个数apply
第一个参数是运行函数的作用域即this
表当前函数运行环境(全局的话就是window对象),第二个为参数数组call
第一个参数为this
,后面的为所有需要传递的参数两者可用于扩充作用域
bind(对象名)
创建函数实例,并绑定传给bind()函数的值给this
基本包装类型:
Boolean, Number, String
不建议显示地创建基本包装类型
自动创建的基本包装类型,只存在于一行代码的执行瞬间,因此不能为其显示的再创建属性(因为会立马被销毁)
永远不使用
Boolean
对象(没啥用感觉)Number
:tofixed(n)
: 按照指定小数位数返回数值的字符串toExponential()
: 指数形式(e型)toPrecision(n)
:按照指定位数显示不建议用
String
:charAt(n)
: 返回给定位置的单个字符charCodeAt(n)
得到字符的ASCII编码concat()
slice() / substring() / substr()
indexOf() / lastIndexOf()
trim()
创建字符串副本,并删除前后所有空格大小写转换的一些函数
模式匹配
match(pattern)
与RegExp的exec()类似search(pattern)
返回查找到的位置replace(pattern, new_str)
替换 第二个参数也可以是函数split(xx)
基于指定的分隔符将一个字符串分割成多个子字符串,并放在一个数组中返回,第二个参数可选,指定数组的大小其它
localeCompare(xxx)
字母表排序fromCharCode(xxx,xxx,...)
接收多个字符编码转换为字符串
单体内置对象:由ECS实现提供,不依赖于宿主环境
Global : ‘兜底儿对象’
eval(xxx)
相当于解析器,可以接受任意js语句
Math :
对数组进行排序,可以调用
1
Math.min.apply(Math, array)
正确指定
this
指针的值