1.值、变量
- 变量是存储数据值的容器。
- 在 JavaScript 中,等号(=)是赋值运算符,而不是“等于”运算符。
- 补充:在ES6语法及之后,统一使用
const、let关键字来声明一个变量。 - 同时声明多个变量
- 同时声明多个变量时,只需要写一个 var, 多个变量名之间用英文逗号隔开。
- var name = '张三', age = 27, number = 100;
- 变量的命名规范:
-
只能由字母(A-Z、a-z)、数字(0-9)、下划线(_)、美元符( $ )组成
-
不能以数字开头。也就是说,必须以字母(A-Z、a-z)、下划线(_)或者美元符( $ )开头。变量名中不允许出现空格。
-
2.数据类型
2.1六种数据类型
2.1.1基本数据类型(值类型):String 字符串、Number 数值、Boolean 布尔值、Null 空值、Undefined 未定义。
#### 字符串
- A.split('',n) ; data.join()
a.charAt(n);
a.indexOf('name',n);
a.lastIndexOf();
a.substring(n,n);
str.toLowerCase str.toUpperCase
- 转义字符: 在 字符串 中我们可以使用`\`作为转义字符,当表示一些特殊符号时可以使用`\`进行转义。
- `\"` 表示 `"`
- `\'` 表示 `'`
- `\\` 表示`\`
- `\r` 表示回车
- `\n` 表示换行。n 的意思是 newline。
- `\t` 表示缩进。t 的意思是 tab。
- `\b` 表示空格。b 的意思是 blank。
#### 数值
数组
- arr.length;
arr.concat(arr1,n,a)
arr.sort(function(n,m){return n-m})
arr.reverse; arr.unshift(arr1.shift()) ; arr.push(arr1.pop)
arr.splice(起点:第几个,删除的个数,插入的数据)
- 在JS中所有的数值都是 Number 类型,包括整数和浮点数(小数)
- **NaN**:是一个特殊的数字,表示Not a Number,非数值。
- Undefined和任何数值计算的结果为 NaN。NaN 与任何值都不相等,包括 NaN 本身。
- 所有的运算都要转换成二进制去计算,然而,二进制是无法精确表示1/10的。因此存在小数的计算不精确的问题。
- 如果加号两边**都是**数值,此时是加。否则,就是连字符(用来连接字符串)。
#### 布尔值:Boolean
- 布尔型有两个值:true 和 false。主要用来做逻辑判断: true 表示真,false 表示假。
- 布尔型和数字型相加时, true 按 1 来算 ,false 按 0 来算。
#### null:空值
- 专门用来表示一个为空的**对象**(例如:`var a = null`)。注意,专门用来表示**空对象**。
- Null类型的值只有一个,就是null。比如 `var a = null`。
- 使用 typeof 检查一个null值时,会返回object。
#### `undefined`:未定义
- **声明**了一个变量,但是没有**赋值**(例如:`var a;`),此时它的值就是 `undefined`。
- Undefined类型的值只有一个,就是undefind。比如
- 使用 type of 检查一个undefined时,会返回undefined。
- null和undefined有很大的相似性。看看null == undefined的结果(true)也就更加能说明这点。但是null === undefined的结果(false)。它们虽然相似,但还是有区别的,其中一个区别是:和数字运算时,10 + null结果为:10;10 + undefined结果为:NaN。
- 任何数据类型和undefined运算都是NaN;
- 任何值和null运算,null可看做0运算。
2.1.2引用数据类型(引用类型):Object 对象。引用数据类型只有一种
- 基本和引用数据类型之间的区别:
- 基本数据类型:参数赋值的时候,传数值。
- 引用数据类型:参数赋值的时候,传地址(修改的同一片内存空间)。
注意:内置对象 Function、Array、Date、RegExp、Error等都是属于 Object 类型。也就是说,除了那五种基本数据类型之外,其他的,都称之为 Object类型。
2.1.3栈内存和堆内存
- JS中,所有的变量都是保存在栈内存中的。
基本数据类型:
基本数据类型的值,直接保存在栈内存中。值与值之间是独立存在,修改一个变量不会影响其他的变量。
引用数据类型:
对象是保存到堆内存中的。每创建一个新的对象,就会在堆内存中开辟出一个新的空间;而变量保存了对象的内存地址(对象的引用),保存在栈内存当中。如果两个变量保存了同一个对象的引用,当一个通过一个变量修改属性时,另一个也会受到影响。
**引用数据类型举例**:
var obj1 = new Object();\
obj1.name = 'smyh';
// 让 obj2 等于 obj1\
var obj2 = obj1;
// 修改 obj1 的 name 属性\
obj1.name = 'vae';
console.log(obj1.name); // 打印结果:vae\
console.log(obj2.name); // 打印结果:vae\
**基本数据类型举例**:
var a = 23;\
var b = a;
a++;
console.log(a); // 打印结果:24\
console.log(b); // 打印结果:23\
2.2类型判断
typeof()`表示“获取变量的数据类型”,返回的是小写,语法为:(两种写法都可以)
// 写法1\
typeof 变量;
// 写法2\
typeof(变量);\
typeof 这个运算符的返回结果就是变量的类型。那返回结果的类型是什么呢?是字符串。
备注 1:为啥 typeof null的返回值也是 object 呢?因为 null 代表的是空对象。
备注 2:typeof NaN的返回值是 number,上一篇文章中讲过,NaN 是一个特殊的数字。
console.log(type []); // 空数组的打印结果:object
console.log(type {}); // 空对象的打印结果:object
代码解释:这里的空数组[]、空对象{} ,为啥他们在使用 typeof 时,返回值也是 object呢?因为这里的返回结果object指的是引用数据类型。空数组、空对象都是引用数据类型 Object。
2.3类型转换
显示类型转换
-
toString()
-
String()
-
Number()
-
parseInt(string)
-
parseFloat(string)
-
Boolean()
| 标题 | |
|---|---|
| 转化为字符串: | |
| 字符串拼接 | - : 格式:变量+"" 或者 变量+"abc" |
| 变量.toString() | - - Number为变量时:a = a.toString(2); // 转换为二进制;如果不指定则默认转换为10进制 |
| String(变量) | - (强制转换): |
| prompt() | 弹出能够让用户输入的对话框;重要的是:用户不管输入什么,都当字符串处理 |
| 转换为number: | |
| Number() 函数 | 字符串 --> 数字:必须是纯数字; 布尔值--->数字; |
| parseInt() | 字符串 --> 整数; - 1.只保留字符串最开头的数字,后面的中文自动消失。- 2.如果字符串不是以数字开头,则转换为 NaN。- 3.如果字符串是一个空串或者是一个全是空格的字符串,转换时会报错。4.如果对非 String使用 parseInt()或 parseFloat(),它会先将其转换为 String 然后再操作。 |
| parseFloat() | 将字符串转换为浮点数; 取整,不四舍五入;parseInt(a, 16); // 【重要】将 a 当成 十六进制 来看待,转换成 十进制 的 num;。 |
- 16 进制的数字,以0x开头- 8 进制的数字,以0开头- 2 进制的数字,0b开头 | |
| 转换为 Boolean | |
| Boolean() | - 情况一:数字 --> 布尔。除了 0 和 NaN,其余的都是 true。也就是说,Boolean(NaN)的结果是 false。- 情况二:字符串 ---> 布尔。除了空串,其余的都是 true。全是空格的字符串,转换结果也是 true。字符串'0'的转换结果也是 true。- 情况三:null 和 undefined 都会转换为 false。- 情况四:引用数据类型会转换为 true。注意,空数组[]和空对象{},转换结果也是 true |
隐式类型转换
| 标题 | |
|---|---|
| isNaN() 函数 | 判断指定的参数是否为 NaN(非数字类型),返回结果为** Boolean 类型**。也就是说:任何不能被转换为数值的参数,都会让这个函数返回 true。 |
自增/自减运算符:++、—- | |
正号/负号:+a、-a | var a = '666';\var b = +a; b转换为numerber |
加号:+ | 1.字符串 + 数字,只要+两边有字符就按字符。2.:Boolean + 数字--->number 3. null + 数字:0+ 4.undefined + 数字: nan |
运算符:-、*、/ | 1.任何非 Number 类型的值做-、*、/运算时,会将这些值转换为Number然后再运算(内部调用的是 Number() 函数),运算结果是 Number 类型。(注:任何值 + 字符串是特例,运算结果是字符串)2、任何的值和字符串做加法运算,都会先转换为字符串,然后再做拼串操作。3、任何值和NaN做运算的结果都是NaN。 |
-
isNaN ()
-
自增/自减运算符:
++、—- -
正号/负号:
+a、-a -
加号:
+ -
运算符:
-、*、/
隐式类型转换(特殊)
-
逻辑运算符:
&&、||、!。非布尔值进行与或运算时,会先将其转换为布尔值,然后再运算,但运算结果是原值。 -
关系运算符:
<、><=>=等。关系运算符,得到的运算结果都是布尔值:要么是true,要么是false。
3.流程控制
流程控制语句分类
- 顺序结构:按照代码的先后顺序,依次执行
- 选择结构:if语句、switch语句
- 循环结构:while语句、for语句
break
-
break可以用来退出switch语句或退出整个循环语句(循环语句包括for循环、while循环。不包括if。if里不能用 break 和 continue,否则会报错)。
-
break会立即终止离它最近的那个循环语句。
-
可以为循环语句创建一个label,来标识当前的循环(格式:label:循环语句)。使用break语句时,可以在break后跟着一个label,这样break将会结束指定的循环,而不是最近的。
通过 break 终止循环语句
for (var i = 0; i < 5; i++) {\
console.log('i的值:' + i);\
if (i == 2) {\
break; // 注意,虽然在 if 里 使用了 break,但这里的 break 是服务于外面的 for 循环。\
}\
}
label的使用
outer:
for (var i = 0; i < 5; i++) {
console.log("外层循环 i 的值:" + i)
for (var j = 0; j < 5; j++) {
break outer; // 直接跳出outer所在的外层循环(这个outer是我自定义的label),外面的都没了里面的怎么会有呢
console.log("内层循环 j 的值:" + j);
}
}
//外层循环 i 的值:0
continue
-
continue可以用来跳过当次循环,继续下一次循环。
-
同样,continue默认只会离他最近的循环起作用。
for (var i = 0; i < 10; i++) {
if (i % 2 == 0) {
continue;
}
console.log('i的值:' + i);
}
打印结果:
i的值:1
i的值:3
i的值:5
i的值:7
i的值:9\
4.运算(表达式、运算符)
数学
比较
> 大于号\
< 小于号\
>= 大于或等于\
<= 小于或等于\
== 等于\
=== 全等于\
!= 不等于\
!== 不全等于
==符号的强调
-
注意
==这个符号,它是判断是否等于,而不是赋值。 -
==这个符号并不严谨,会做隐式转换,将不同的数据类型,转为相同类型进行比较(大部分情况下,都是转换为数字)。 -
undefined 衍生自 null,所以这两个值做相等判断时,会返回true。
-
NaN不和任何值相等,包括他本身。
===全等符号的强调 -
全等在比较时,不会做类型转换。要保证绝对等于(完全等于), -:
==的反面是!=,===的反面是!==。
三元运算符
三元运算符也叫条件运算符。
条件表达式 ? 语句1 : 语句2;\
- 如果该值为true,则执行语句1,并返回执行结果
- 如果该值为false,则执行语句2,并返回执行结果
逻辑
&& || !
与运算的返回结果:(以两个非布尔值的运算为例)
-
如果第一个值为false,则直接返回第一个值;不会再往后执行。
-
如果第一个值为true,则返回第二个值(如果所有的值都为true,则返回的是最后一个值)。
或运算的返回结果:(以两个非布尔值的运算为例)
-
如果第一个值为true,则直接返回第一个值;不会再往后执行。
-
如果第一个值为false,则返回第二个值((如果所有的值都为false,则返回的是最后一个值)。
实际开发中,我们经常是这样来做「容错处理」的:
当成功调用一个接口后,返回的数据为 result 对象。
这个时候,我们用变量 a 来接收 result 里的图片资源。通常的写法是这样的:
if (result.resultCode == 0) {
var a = result && result.data && result.data.imgUrl || 'http://img.smyhvae.com/20160401_01.jpg';
}
上方代码的意思是,获取返回结果中的`result.data.imgUrl`这个图片资源;
如果返回结果中没有 `result.data.imgUrl` 这个字段,就用 `http://img.smyhvae.com/20160401_01.jpg` 作为**兜底**图片。
这种写法,在实际开发中经常用到。
Unicode 编码
优先级
运算符的优先级如下:(优先级从高到低)
- `.`、`[]`、`new`
- `()`
- `++`、`--`
- `!`、`~`、`+`(单目)、`-`(单目)、`typeof`、`void`、`delete`
- `%`、`*`、`/`
- `+`(双目)、`-`(双目)
- `<<`、`>>`、`>>>`
- 关系运算符:`<`、`<=`、`>`、`>=`
- `==`、`!==`、`===`、`!==`
- `&`
- `^`
- `|`
- `&&`
- `||`
- `?:`
- `=`、`+=`、`-=`、`*=`、`/=`、`%=`、`<<=`、`>>=`、`>>>=`、`&=`、`^=`、`|=`
- `,`
5.函数
arguments: 一个包含了传递给当前执行函数参数的类似于数组的对象。 arguments[I];arguments.length: 传给函数的参数的数目。
函数声明&函数表达式&构造函数
//构造函数
var multiply = new Function('x', 'y', 'return x * y');
使用用 '`new Function'定义的函数没有函数名。`
//函数表达式,赋值给multiply
var multiply = function(x, y) {
return x * y;
};
? 函数表达式定义的函数继承了当前的作用域。换言之,函数构成了闭包。
另一方面,Function构造函数定义的函数不继承任何全局作用域以外的作用域(那些所有函数都继承的)。
//nultiply函数声明
function multiply(x, y) {
return x * y;
} // 没有分号
!!!函数声明定义的函数可以在它被声明之前使用,其他的不行。
developer.mozilla.org/zh-CN/docs/…
回调函数
箭头函数
- let sum = (a, b) => { // 花括号表示开始一个多行函数 let result = a + b; *return result; //
如果我们使用了花括号,那么我们需要一个显式的 “return”*}; alert( sum(1, 2) ); // 3
// 当只有一个参数时,圆括号是可选的:
(singleParam) => { statements }
singleParam => { statements }
// 没有参数的函数应该写成一对圆括号。
() => { statements }
- 没有自己的
this,arguments,super或new.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。
//this,在直接调用函数的时候可以借用,箭头函数没有this,而是直接从上下文中决定
//**arguments**
箭头函数也没有 `arguments` 变量。
当我们需要使用当前的 `this` 和 `arguments` 转发一个调用时,这对装饰器(decorators)来说非常有用。
例如,`defer(f, ms)` 获得了一个函数,并返回一个包装器,该包装器将调用延迟 `ms` 毫秒:
function defer(f, ms) {
return function() {
setTimeout(() => f.apply(this, arguments), ms)
};
}
function sayHi(who) {
alert('Hello, ' + who);
}
let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("John"); // 2 秒后显示:Hello, John
不用箭头函数的话,可以这么写:
function defer(f, ms) {
return function(...args) {
let ctx = this;
setTimeout(function() {
return f.apply(ctx, args);
}, ms);
};
}
在这里,我们必须创建额外的变量 `args` 和 `ctx`,以便 `setTimeout` 内部的函数可以获取它们。