JavaScript 诞生于 1995年,是一种专为与网页交互而设计的脚本语言。由三种不同部分组成:
ECMScript 是这本语言的基础,规定了这门语言的下列组成部分:
文档对象模型(DOM, Document Object Model) 是针对XML但经过扩展用于HTML的应用程序编程接口。提供了以下方法和接口的定义:
浏览器对象模型(BOM, Browser Object Model) 用来访问和操作浏览器窗口,有以下的扩展:
在 HTML 内部直接写入 片断,这种写法要注意JavaScript 是单线程的,如果在初始化页面的时候,你的代码中存在大量同步运行的代码,导致 JS 线程一直处于繁忙状态,这时候用户在页面上进行交互时将不会得到任何反应,就像是卡死了一样。想了解具体原因,参考文章浏览器渲染原理
ESCAScript 的变量是 松散类型 的,就是说可以用来保存任何类型的数据。也就是说一个变量就是一个占位符。
var a = 'hi';
a = 10;
定义变量可以使用 var 操作符,定义多个变量,每个变量之间用 逗号 分开,如果 省略 var 操作符可以定义 全局变量,未经初始化的变量,会保存一个特殊的值—— undefined
function show() {
var _message = '局部变量',
_name = 'lily';
g_message = '全局变量';
}
show();
console.log(g_message); // 全局变量
console.log(_message); // _message is not defined
在 ESCScript 中变量会被自动 提升
console.log(enhance); // 变量提升
var enhance = "变量提升";
ECMAScript 有6种数据类型,其中5种基本的数据类型: Undefined、Null、Boolean、Number和String,还有1种复杂的数据类型: Object。一般使用 typeof 检查5种基本的数据类型,使用 instanceof 检查是哪种复杂的数据类型。
typeof
常见的就不说了,说几个可能容易混或者错的。
值 | 使用typeof操作符返回 |
---|---|
值未初始化 | ‘undefined’ |
值对象、null | ‘Object’ |
值是函数 | ‘function’ |
// 未初始化的变量
var uninital;
console.log('未初始化的变量:---' +typeof uninital); // undefined
// 未定义的变量
console.log('未定义的变量:---' + typeof liy); // undefined
// 值为null
var obj = null;
console.log('值是null的时候:---' + typeof obj); // object
// 值未函数
function add (a, b) {
return a + b;
}
console.log('值是funciton:---' + typeof add); // function
Boolean 类型
Boolean 类型是 ECMAScript 中使用最多的一种类型,只有两个字面量值: true、false;区分大小写,也就是说 True 不是布尔值。
流程控制语句(例如 if 语句)自动执行 转型函数 Boolean()。
var message = "hello world";
if (message) {
console.log('转换为 true'); // 执行这句
} else {
console.log('转换为 false');
}
下表给出了几种数据类型及其对应的转换规则
数据类型 | 转换为true 值 | 转换为false值 |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | ‘’(空字符串) |
Number | 任何非0数字(包括无穷大) | 0、NaN |
Object | 任何对象 | null |
Undefined | 不适用 | undefined |
Number 类型
var result = Number.MAX_VALUE + Number.MAX_VALUE;
console.log('数值是否是有穷的:' + isFinite(result)); // false
console.log(isNaN(10)); // false
console.log(isNaN('10')); // false
console.log(NaN == NaN); // false
console.log(Number('hello')); // NaN
console.log(Number('')); // 0
String 类型
转换为字符串有两种方式 toString([几进制]) 和 String(名)
var num = 10;
console.log(num.toString()); // '10'
console.log(num.toString(2)); // '1010'
console.log(String(10)); // '10'
Object 类型
访问对象的属性有两种方式
person['name']
person.name
布尔操作符
逻辑非和逻辑或都是 短路 操作符
逻辑与
如果第一个操作数是对象,则返回 第二个 操作数;
如果第二个操作符是对象,则只有第一个操作数的求值结果是 true 的情况下才会返回该 对象;
var obj = {
name: 'lily',
}
console.log(obj && true); // true
console.log(true && obj); // {name: 'lily'}
逻辑与
如果第一个操作数是对象,则返回 第一个 操作数;
如果两个操作数都是对象,则返回 第一个 操作数;
关系操作符
如果两个操作数都是字符串,则比较两个字符串对应的 字符编码,所以字符串比较的时候一般都转换为大写(或者小写);
任何操作数与 NaN 进行比较,结果都是 false;
console.log('Brink'.toLowerCase() < 'alpha'.toLowerCase()); // false
console.log(NaN < 3); // false
for 语句
在 ECMAScript 中没有块级作用域的概念,因此循环内部定义的变量也可以在外部访问到。
for (var i = 0;i < 10 ; i++) {}
console.log(i); //10
其实以上的代码就相当于
var j;
for (j = 0; j < 10; j ++) {}
console.log(j);
for-in 语句
for-in 语句用来遍历对象的属性,但此时的对象不能是null或者undefined。
switch 语句
switch 语句在比较值的时候使用的是全等
看一个我觉得很新颖的语句
var num = 18;
switch (true) {
case num < 0:
alert('less than 0');
break;
case num > 0 && num < 10:$
alert('between 0 and 10');
breka;
default:
alert('more than 10');
}
函数
可以向 ECMAScript 函数传递任意数量的参数,并且可以通过arguments对象来访问这些参数。即便你定义的函数只接收两个参数,在调用这个函数也未必一定传递两个参数,可以传递一个、三个甚至不传递参数。如果没传递值的命名参数将自动被赋予undefined值。
function add() {
if (arguments.length == 1) {
alert(arguments[0] + 10);
} else {
alert(arguments[0] + arguments[1]);
}
}
add(10); // 20
ECMAScript 变量包含两种不同类型的值:基本类型和引用类型值。
基本类型的值
基本类型的值在内存中占据固定大小的空间,因此保存在 栈 内存中
如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把值复制到新变量的位置上。
var num1 = 5;
var num2 = num1;
传递参数的时候是按 值 传递的,和复制变量一样。
引用类型
引用类型的值是对象,保存在 堆 内存中;
从一个变量向另一个变量复制引用类型的值时,同样也将存储在变量对象中的值复制一份到新分配的空间中。不同的是,这个值的副本实际上时一个指针。
var obj1 = new Object();
var obj2 = obj1;
但是当为对象添加属性的时候,操作的是实际对象。
obj1.name = "lily";
console.log(obj2.name); // lily
传递参数的时候是按 值 传递的,和引用类型复制一样。
- 执行环境
执行环境定义了变量或函数有权访问的其他数据,决定了他们的行为;
执行环境可以分为**全局执行环境** 和 **每个函数自己的执行环境**;
- 作用域链
代码在执行环境中执行,会创建对象的一个 **作用域链**,这个作用域链可以保证对执行环境有权访问的所有变量和函数的有序访问。
优化内存占用的最佳方式,就是为代码只保存必要的数据。一旦数据不再用了,最好通过将其值设置为 null 来释放引用。
function cretePerson(name) {
var localPerson = new Object();
localPerson.name = name;
return localPerson;
}
var g_person = cretePerson('lily');
g_person = null;
在 ECMAScript中,引用类型是一种数据结构,常用的有:Object、Date、RegExp、Function、基本包装类型、单体内置对象。
插入
arr[length] = 'add data from bottom';
arr.push('add data from bottom');
arr.unshift('add data from head');
splice(2,0,'red','green');
,三个参数,第一个是位置,第二个是要删除的数据个数,第三个数据为插入的数据;删除
arr[length] = arr.length - 1;
arr.pop();
arr.shift();
arr.splice(0,1);
,两个参数,第一个参数是位置,第二个参数是要删除的个数;替换
arr.splice(2,1,'red')
检测数组
检测是否是数组
if(Array.isArray(value)){}
转换为字符串的方法
排序方法
合并
var color1 = ['color1', 'color2'];
var color2 = color1.concat('yellow'); // color1,color2,yellow
位置方法
迭代
10.归并数组
- reduce
- reduceRight
函数分为函数声明和函数表达式,函数表达式可以随时访问,因为函数声明提升。
arguments 对象
arguments 对象主要用途是保存函数参数,包含一个特殊属性callee属性,是个指针,指向拥有这个arguments对象的函数;
function factorial (num) {
if (num < 1) {
return 1;
} else {
return num * arguments.callee(num - 1);
}
}
console.log(factorial(4)); //24
this 对象
this 引用的是函数执行环境对象
window.color = 'red';
var obj = {color: 'obj bule'};
function showColor () {
console.log(this.color);
}
showColor(); // red
obj.sayColor = showColor;
obj.sayColor(); // obj bule
apply(运行函数的作用域, 参数数组)
window.color = 'window color red';
var obj = {color: 'obj color blue'};
function showColor(data) {
console.log(this.color); //window color red
console.log(`传入数据${data}`);
}
showColor();
showColor.apply(obj, ['我用了apply']);
// obj color blue 传入数据我用了apply
call(运行函数的作用域,其余参数)
window.color = 'window color red';
var obj = {color: 'obj color blue'};
function showColor(data) {
console.log(this.color); //window color red
console.log(`传入数据${data}`);
}
showColor.call(obj, '我用了call');
//obj color blue
//传入数据我用了call
1. length
2. charAt(位置)
3. charCodeAt(位置):返回字符编码
4. substring(start, [end])
5. substr(start, [end])
6. slice(start, [end])
7. indexof(要查找内容,位置)
8. trim: 去除空格
9. toUpperCase
10. toLocaleUpperCase
11. toLowerCase
12. toLocalLowerCase
13. split(切割符),返回数组
toString 和 toLocaleString() 的区别
var num = 1234
num.toString(); // 1234
num.toLocalString(); // 1,234
var date = new Date();
date.toString(); //Tue Jul 09 2019 21:28:06 GMT+0800 (中国标准时间)
date.toLoacalString(); //"2019/7/9 下午9:28:06"
总结:该字符串与执行环境的地区对应
ps: 欢迎大家添加讨论
一元运算符
var age = 27;
var afterAge = ++age + 1; // age 会执行为++,变为 28 再加1,结果为29
console.log(age, afterAge); // 27, 29
var age = 27;
var afterAge = age++ + 1; // 会先用age 进行 +1 操作,然后再进行++操作
console.log(age, afterAge); // 28, 28
位操作符-按位非
~
var num = 25;
var nonNum = ~num; // -26
布尔操作符
逻辑非
false
;Boolean()
,其中第一个非,无论什么操作数返回一个布尔值,而第二个逻辑非操作会对该布尔值求反。逻辑与
{ name: 'lily'} && { age: 27 } // {age: 27}
逻辑或
短路操作:如果第一个的求值结果为 true
, 就不会计算对第二个操作数求值;
null, undefined 用Number() 转换
'a' < 'B' // false
'a'.toLocaleLowerCase() < 'B'.toLocaleLowerCase() // true
false < true // true
for-in 语句
var num = 0;
for(let i = 1; i < 10; i++) {
if (i % 5 === 0) {
break;
}
num++;
console.log(i);
}
// 1 2 3 4
let num2 = 0;
for(let i = 1; i < 10; i ++) {
if (i % 5 === 0) {
continue;
}
num2++;
console.log(i);
}// 1 2 3 4 6 7 8 9
label
语句,比如跳出双循环let num3 = 0;
outermost:
for(let i = 0; i < 10; i++) {
for(let j = 0; j < 10; j++) {
if(i === 5 && j == 5) {
break outermost;
}
num3++;
}
}
// num3 55
switch 语句
break
关键字会导致代码执行流跳出switch 语句,如果省略了break关键字,就会导致执行完当前的case,继续执行下一个case, 通常这种情况需要添加注释;switch(num) {
case 1:
case 2:
/**合并两种注释**/
console.log('条件1 和条件2');
break;
default:
break;
}
函数参数
function test(param1, param2)
,调用的时候可以传入0个或者多个参数,参数在内部用一个数组来表示,函数内部接收的是这个数组,可以用arguments对象来访问这个参数数组function sum(num1, num2) {
if(arguments.length === 1) {
return 10 + num1;
} else if (arguments.length === 2) {
return num1 + num2;
} else {
return '参数有点多';
}
}
sum() // "参数有点多"
sum(1) // 11
sum(2, 3) // 5
检测类型
typeof null
是 Object
,typeof 函数
返回 function
基本类型和引用类型的值
ECMAScript 包含两种不同数据类型的值: 基本类型值和引用类型值
“基本数据类型是按值访问的,因为可以操作保存在变量中实际的值”;“引用类型的值是保存在内存中的对象。与其他语言不同,javascript 不允许直接访问内存中的位置,也就是不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用访问的。”
以下是对于上面这句话理解的剖析:
值类型和引用类型在内存上的存储区域:
程序员开发涉及到的内存区域: 栈,堆,静态存储区域;
堆和栈的概念:
值和引用类型的区别:
值类型的值是存储在内存的栈当中;引用类型的值是存储在内存的堆中;
传递值类型和传递引用类型的时候,传递方式不一样。值类型我们称之为值传递,引用类型我们称之为引用传递。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gEMof9Gd-1592273613965)(https://user-images.githubusercontent.com/16410254/61796800-c0696b00-ae58-11e9-82e5-ae69385a72fc.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U35k45es-1592273613984)(https://user-images.githubusercontent.com/16410254/61796880-e0009380-ae58-11e9-9caa-417db777fb05.png)]
javascript中的变量
怎么理解 javascript不允许直接访问内存中的位置,不能直接操作对象的内存空间?
js语言本身定义确实不允许,其次,考虑js运行环境,是用在浏览器上,浏览器一般情况也不能访问内存,不然,你想像一下,浏览器可以访问读写电脑上的内存,那将是多么恐怖的事儿(随便写一个小程序就可以控制你电脑,拿到你电脑上所有的东西了。)。
作为一门高级语言,JS并不像低级语言C/C++那样拥有对内存的完全掌控。JS中内存的分配和回收都是自动完成,内存在不使用的时候会被垃圾回收器自动回收。
值传递和引用传递
function setName(obj) {
obj.name = 'lily';
obj = new Object();
obj.name = 'lucy';
}
let person = new Object();
setName(person);
person.name // lily
如果引用类型是按引用传递的话,那么obj
和 person
是同一个对象,当obj = new Object()
的时候person
指向堆中的对象也会变,输出的person.name 会是 lucy
执行环境和栈
原文网址:https://juejin.im/entry/5833f18fe696c9004d6da42e
这篇文章我将会深入地讨论JavaScript中最根本的一部分——Execution Context(执行上下文)。在文章结束的时候,你应该对解释器的工作原理有一个比较清晰的理解,对于为什么会存在‘变量提升’,它们的值又是如何被真正确定的这些问题有一个正确的答案。
什么是Executin Context(执行上下文)
当JavaScript代码执行的时候,执行环境是很重要的,它可能是下面三种情况中的一种:
全局 code(Global code)——代码第一次执行的默认环境
函数 code(Function code)——执行流进入函数体
Eval code(Eval code)——代码在eval函数内部执行
在网上你能够读到许多关于作用域的资料,这篇文章的目的是让事情变得简单些。让我们来思考下execution context这个词,它与当前代码的环境 / 作用域是等价的。好了,说的够多了,让我们来看一个包含global和function / local context的例子吧。
image 这里没有什么特别的地方,我们有一个global context被紫色的框框着,还有三个不同的function context,分别被绿色、蓝色、橘色的框框着。在你的程序中,有且仅能有一个global context,并且它能够被任何其他的context访问到。你能够拥有任意多个function context,并且每个函数被调用的时候都会生成一个新的context。它会生成一个私有作用域,并且在它内部声明的任何东西都不能直接在它的外部访问。就像上面的例子,一个函数可以直接访问它外面的变量,但是外部的context就不能直接访问在内部声明的变量或者函数。为什么会这样?如何准确的理解这段代码的执行?
以上是文章摘要 阅读更多请点击——>右下角的more 以下是余下全文
Execution Context Stack(执行上下文栈)
浏览器中的JavaScript解释器是单线程的。意思就是说在浏览器中,同一时间只能做一件事,其它的行为和事件都会在Execution Stack中排队。下面这个图表就是一个单线程栈的抽象描述:
image
我们已经知道,当浏览器第一次加载你的script的时候,默认进入global execution context。如果,你在全局代码中调用了函数,程序序列流就会进入被调用的函数中,生成一个新的execution context并且把它压入execution stack的顶部。
如果你在当前函数内调用其他函数,会发生同样的事情。代码的执行流会进入内部函数,生成一个新的execution context,并且将它压入existing stack。浏览器总是会执行stack顶部的executin context,当被执行的函数上下文执行完成后,它将会弹出栈顶,然后将控制权返回给当前栈中的下一个对象。下面是一个循环函数执行栈的例子:
(function foo(i) {
if (i === 3) {
return;
}
else {
foo(++i);
}
}(0));
image
函数foo递归调用了3次,每次 i 增长1。函数 foo 每次调用后,都出生成一个新的execution context。当一个context执行完成后,它就会出栈并且把控制权返回给下面的context,直到再次到达global context。
关于execution stack有5个关键点需要记住:
单线程
同步执行
1个Global context
无限制的函数context
每个函数调用都会创建新的execution context,即使是自己调用自己。现在我们知道了函数每次被调用的时候,一个新的execution context就会被创建。无论如何,在JavaScript解释器内部,每次调用执行execution context都有两个阶段:
创建阶段【在函数被调用的时候,但是内部代码执行之前】
创建Scope Chain
创建变量、函数和参数
确定 “this” 的值
激活 / 代码执行阶段
变量赋值、引用函数和解释 / 执行代码。
每个execution context在概念上可以用一个对象来表示,这个对象有三个属性:
executionContextObj = {
‘scopeChain’: { /* variableObject + all parent execution context’s variableObject / },
‘variableObject’: { / function arguments / parameters, inner variable and function declarations */ },
‘this’: {}
}
执行对象 / 变量对象【AO/VO】
这个executionContextObj在函数被调用的时候创建,但是是在真实函数代码被执行之前。这个就可以理解为第一阶段,创建阶段(Creation Stage)。在这里,解释器通过搜索函数的形参和传入的实参、本地函数的声明和本地变量的声明来创建executionContextObj。搜索的结果就是executionContextObj对象中的variableOject属性。
这里是解释器执行代码的一个伪综述:
找到调用函数的代码。
在执行函数代码之前,创建execution context。
进入创建阶段:
初始化Scope Chain
创建variable object
创建实参对象(arguments object),检查context的形参(parameters),初始化参数的名称和参数值并且创建一份引用的拷贝。
扫描context中的函数声明:
为每一个函数在varible object上创建一个属性,属性名就是函数名,含有一个指向内存中函数的引用指针。
如果函数名已经存在了,这个引用指针的值将会被重写。
扫描context中的变量申明:
为每一个变量在variable object上创建一个属性, 属性名就是变量名并且将变量的值初始化为undefined。
如果变量名在variable object中已经存在,那就什么都不会发生,并且继续扫描。
激活 / 代码执行阶段:
运行 / 解释context中的函数代码,并且根据代码一行一行的执行,为变量赋值。
让我们来看一个例子:
function foo(i) {
var a = ‘hello’;
var b = function privateB() {
};
function c() {
}
}
foo(22);
当调用foo(22)时,创建阶段(creation stage)时,context是下面这个样子:
fooExecutionContext = {
scopeChain: { … },
variableObject: {
arguments: {
0: 22,
length: 1
},
i: 22,
c: pointer to function c()
a: undefined,
b: undefined
},
this: { … }
}
因此,你可以看到,在创建阶段(creation stage)只负责对属性名称(变量名)的定义,但是并没有给它们赋值,当然这里有一个例外就是formal arguments / parameters(实参 / 形参)。当创建阶段完成以后,执行流进入函数内部,激活执行阶段(execution stage),然后代码完成执行,context是下面这个样子:
fooExecutionContext = {
scopeChain: { … },
variableObject: {
arguments: {
0: 22,
length: 1
},
i: 22,
c: pointer to function c()
a: ‘hello’,
b: pointer to function privateB()
},
this: { … }
}
关于Hoisting(变量提升)
在网上你可以找到很多定义JavaScript中hoisting这个词的文献,解释变量和函数的声明在它们的作用域中被提前。但是,没有从细节上解释为什么会发什么这种现象。通过了解解释器如何创建activation object,就很容易知道这种现象发生的原因了。看下面这个例子:
(function() {
console.log(typeof foo); // function pointer
console.log(typeof bar); // undefined
var foo = ‘hello’,
bar = function() {
return ‘world’;
};
function foo() {
return ‘hello’;
}
}());
现在我们可以回答下面这些问题了:
在foo声明之前,为什么我们可以访问它?
如果我们来跟踪creation stage, 我们知道在代码执行阶段之前,变量已经被创建了。因此在函数流开始执行之前,foo已经在activation object中被定义了。
foo 被声明了两次,为什么 foo 最后显示出来是一个function,并不是undefined或者是string?
尽管 foo 被声明了两次,我们知道,在创建阶段,函数的创建是在变量之前的,并且如果属性名在activation object中已经存在的话,我们是会简单的跳过这个声明的。
因此,对 function foo()的引用在activation object上先被创建了,当解释器到达 var foo 时,我们会发现属性名 foo 已经存在了,因此代码什么都不会做,继续向下执行。
为什么 bar 是undefined?
bar实际上是一个变量,并且被赋值了一个函数的引用。我们知道变量是在创建阶段被创建的,但是它们会被初始化为undefined,所以bar是undefined。希望现在你对JavaScript解释器如何执行你的代码能有一个好的理解了。理解execution context and stack会让你知道为什么你的代码有时候会输出和你最初期望不一样的值。
作用域链:
推荐两篇文章:
http://blog.xieliqun.com/2016/10/06/scope-chain-2/
http://blog.xieliqun.com/2016/10/06/scope-chain/
附一张自己整理的图片
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tkNg7qGL-1592273641906)(https://user-images.githubusercontent.com/16410254/64535352-b4befe80-d349-11e9-8e4c-e75e6550422f.jpg)]
立即执行函数
function test() {
var ele = document.getElementById('#test');
var id = ele;
ele.onclick = function() {
console.log(id);
}
ele = null;
}
模仿块级作用域
特权方法
定义:有权访问私有变量和私有函数的公有方法;
可以使用构造函数模式、原型模式、模块模式、增强的模块模式来实现
-构造函数模式
function Test() {
var name = 'lily';
// 特权方法
this.setName = function(val) {
name = val;
}
}
(function() {
var name = 'lily';
Person = function() {};
// 特权方法
Person.prototype.setName = function(val) {
name = val;
}
})();
var singleton = function() {
var name = 'lily';
function privateSay() {
console.log('hello');
}
// 返回对象
return {
publicPropterty: true,
publicMethod: function() { name ='luce'; return privateSay(); }
}
}();
var singleton = function(){
// 私有变量
var components = new Array();
// 初始化
components.push(new BaseCom());
// 创建指定类型的是咧
var app = new BaseCom();
// 公共的接口和方法
app.getComponentCount = function () { return components.length; }
return app;
}();
javascript 内存管理
function createPerson(name) {
var localPerson = new Ojbect();
localPerson.name = name;
return localPerson;
}
var glPerson = createPerson('lily');
glPerson = null // 手工解除引用
Array 类型
length
属性不是只读的,因为可以在数组的末尾移除元素或者添加元素
var colors = ['red', 'blue'];
colors.length = 1;
console.log(colors); // ['red']
var colors = ['red', 'blue'];
colors[colors.length] = 'green';
console.log(colors); // ['red', 'blue', 'green'];
检测数据类型
Array.isArray(val)
判断 value
是不是数组;转换方法
toString()
: 以 ,
形式拼接每个值的字符串arr.valueof()
: 返回的是数组本身;arr.join(指定分隔符)
: 用指定分隔符拼接每个值的字符串;模拟栈
let arr = [1];
arr.push(2);
arr.pop();
模拟队列
let arr = [1, 2, 3];
arr.push(4);
arr.shift(); // 1
重排序方法
var arr = [1, 2, 3]; arr.reverse(); // [3, 2, 1]
function compare(value1, value2) {
if(value1 < vlaue2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
var values = [0, 5, 1, 10, 15];
values.sort(compare);
console.log(values); // [0, 1, 5, 10, 15]
操作方法
concat()
: 基于当前的数组,返回一个新的数组,不改变原来的数组,接收到的参数追加到原来数组的末尾;var arr1 = [1, 2]; var arr2 = arr1.concat([5]); // [1, 2, 5]
slice(start, end)
: 返回新数组,不影响原来的数组,截取 start~end-1 的元素,如果第二个参数没有的话,默认为到末尾; var sliceArr = [1, 2, 3]
var transliceArr = sliceArr.slice(1, 2) // [2]
-```splice(index, delNum, item)``: 会改变原来的数组,f返回删除的元素,第一个参数为位置,第二个参数为删除几项,第三个参数为添加的数据。
var colors = ["red", "green", "black"];
var removed = colors.splice(0, 1);
console.log(removed); // ['red'];
removed = colors.splice(1, 0, 'white'); // ["green", "white", "black"]
console.log(removed); // []
colors.splice(1, 1, 'red', 'yellow'); // ["green", "red", "yellow", "black"]
位置方法:
迭代方法:
var num = [1, 2, 3, 4, 5];
var everyRes = num.every((item) => return item >2); // false
var someRes = num.some(item => return item > 2); //true;
var filterRes = num.filter(item => return item > 2); // [3, 4, 5];
var mapRes = num.map(item => return item * 2); // [2, 4, 6, 8, 10]
归并方法
reduce(prev, cur, index, array)
和 reduceRight(prev, cur, index, array)
这个函数返回任何值,都会作为第一个参数传入下一项。var num = [1, 2, 3]; var sum = num.reduce((prev, cur, index ,arr) => return prev + cur ); // 6
Date 类型
var start = +new Date();
// do some thing
var end = +new Date();
var result = end - start;
valueOf()
方法,返回日期的毫秒数,所以可以使用**比较操作符来比较日期值。RegExp 类型
字面量创建正则表达式
var expression = /pattern/ flags;
flags 包含3种形式
-元字符不要转义
( ) { } [ ] \ ^ $ | ? * + .
pattern.test(text)
目标字符串是否和模式匹配,返回Boolean;Function 类型
函数实际上是对象,每个函数是 Function 类型的实例;函数名实际上是指向某个函数的指针,不会与某个函数绑定;
定义:
function sum(num1, num2) { return num1 + num2 }
;var sum = function(num1, num2) { return num1 + num2 };
;函数声明和函数表达式
var test = function () {} test()
; 函数声明不能直接调用function test() {} ()
; // 函数声明
sum(4,5); // 9
function sum(a, b) { console.log(a + b)}
// 函数表达式
add(4, 5);
var add = function(a, b) { console.log(a + b) }
// 递归
var factorial = (function f()num {
if( num < 1) { return 1} else { return num * f(num -1)}
})
函数声明提升:
JS引擎会在正式执行代码之前进行一次”预编译“,预编译的函数,查找函数声明,作为GO属性,值赋予函数体(函数声明优先);找变量声明,作为GO属性,值赋予undefined;这样就是函数声明和函数表达是式的不同
函数的内部属性
arguments
对象的函数; function sum(a, b) {
console.log(arguments.callee); // sum 这个函数
}
function outer() { inner() }
function inner() { console.log(arguments.callee.caller) } // outer 这个函数
function thisDemo() {
console.log(this);
}
thisDemo(); // this 是window
var obj = {};
obj.demo = thisDemo;
obj.demo(); // this 就是obj
函数属性
function sum(a, b) { return a + b; } sum.length // 2
函数的方法
var color = 'red';
function sayColor() { console.log(this.color) }
var banana = { color: 'yellow' }
sayColor(); // red
sayColor(banana); // yellow;
var color = 'red';
var banana = { color: 'yellow' }
function sayColor () { console.log(this.color) }
var bindSayColor = sayColor.bind(banana);
bindSayColor(); // 'yellow', 虽然在全局执行,但是this是banana;
基本包装类型 - String
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dZsDG3qb-1592273710370)(https://user-images.githubusercontent.com/16410254/63694834-e87a2e80-c849-11e9-91c1-df0dad90df75.png)]
单体内置对象 - Global对象
URI 编码方法
encodeURI(uri)
对整个uri 进行编码,对本身属于URI的特殊字符不进行编码,例如 /
;encodeURIComponent(uri)
对uri中的一段进行编码,对所有非标准字符不进行编码var uri = 'http://www.baidu.com/lily index.html#start'
encodeURI(uri); // "http://www.baidu.com/lily%20index.html#start"
encodeURIComponent(uri); // "http%3A%2F%2Fwww.baidu.com%2Flily%20index.html%23start"
decodeURI(uri)
decodeURIComponent(uri)
在任何环境的情况下返回全局对象的方法
var global = function() { return this }();
单体内置对象- Math对象
// 取数组中的最大值
var values = [1, 2, 3, 5, 8];
var max = Math.max.apply(Math, values);
舍入方法
25.1
向上舍入是26
random():生成一个(0<= x < 1)之间的随机数
// 值 =Math.floor(Math.random() * 总数 + 第一个值)
function selectFrom(lowerVal, upperVal) {
var choices = upperVal - lowerVal + 1;
return Math.floor(Math.random() * choices + lowerVal);
}
// 例如2~9之间的随机数
var num = Math.floor(Math.random() * 8 + 2 );