4.1 js基础语法

158 阅读9分钟

1.值、变量

  • 变量是存储数据值的容器。
  • 在 JavaScript 中,等号(=)是赋值运算符,而不是“等于”运算符。
  • 补充:在ES6语法及之后,统一使用 constlet关键字来声明一个变量。
  • 同时声明多个变量
    • 同时声明多个变量时,只需要写一个 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栈内存和堆内存

www.cnblogs.com/whgw/archiv…

  • 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-avar 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 }
  • 没有自己的thisargumentssupernew.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` 内部的函数可以获取它们。