JavaScript基础

JavaScript基础

JavaScript代码的存在形式

  • HTML文件中

    1
    2
    3
    <script type="text/javascript">
    //JavaScript代码
    </script>
  • js文件中,在HTML中引入(可使用远程js文件路径)
    <script src="*.js路径"></script>

  • 浏览器从上到下解释HTML和js代码,为了保证页面首先显示,一般要将CSS文件引入写在head标签中;js代码块和引入写在body内部的最下面。

js注释

  • 双斜杠单行注释//
  • /* 斜杠星,星斜杠,多行注释 */

js变量

  • name='alex'; //全局变量
  • var name='alex'; //局部变量

js基本数据类型

  • 数字typeof->number
    • js不区分整数和浮点数,所有数字均用浮点数表示
    • parseInt() ,字符串转数字;另外用法:parseInt('101',16)=>把101按16进制计算,返回对应10进制值,这里的进制可以是任意2,4,6,8,36都行,可以用来计算次方
    • parseFloat() 字符串转浮点
    • 0x 0X开头的数字表示十六进制
    • 0b 0B开头表示二进制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var num = 3.14
num.toExponential();
// 通过科学计数法表示:上述返回为"3.14e+0"
// 可提供位数参数num.toExponential(3);->"3.140e+0"

num.toFixed()
// 指定小数位,位数参数默认值为0,上述返回为:"3"
num.toFixed(1) // 返回为"3.1"

num.toPrecision() // 按精度返回
num.toPrecision(5) // "3.1400"

num.toString() //转字符串

num.toLocaleString('zh-Hans-CN-u-nu-hanidec')
// 输出:三.一四,用到时要查文档,各种参数返回不同

isFinite(num) // 判断是否是正常数字,返回布尔值

isNaN(num) // 判断是否非数字,返回布尔值
  • 布尔类型
    布尔类型仅包含真假,与Python不同的是其首字母小写。
    • == 比较值相等
    • !=不等于
    • === 比较值和类型相等
    • !=== 不等于
    • || 或
    • && 且
  • 字符串typeof->string
    字符串是由字符组成的数组,但在JavaScript中字符串是不可变的:可以访问字符串任意位置的文本,但是JavaScript并未提供修改已知字符串内容的方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    //常见功能
    obj.length 长度
    obj.trim() 移除空白
    obj.trimLeft()
    obj.trimRight)
    obj.charAt(n) 返回字符串中的第n个字符
    obj.concat(value, ...) 拼接
    obj.indexOf(substring,start) 子序列位置
    obj.lastIndexOf(substring,start) 子序列位置
    obj.substring(from, to) 根据索引获取子序列
    obj.slice(start, end) 切片
    obj.toLowerCase() 大写
    obj.toUpperCase() 小写
    obj.split(delimiter, limit) 分割
    obj.search(regexp) 从头开始匹配,返回匹配成功的第一个位置(g无效)
    obj.match(regexp) 全局搜索,如果正则中有g表示找到全部,否则只找到第一个。
    obj.replace(regexp, replacement) 替换,正则中有g则替换所有,否则只替换第一个匹配项,
    $数字:匹配的第n个组内容;
    $&:当前匹配的内容;
    $`:位于匹配子串左侧的文本;
    $':位于匹配子串右侧的文本
    $$:直接量$符号
  • 字符串拼接ES6

1
2
3
4
5
6
var name = 'lmc';
var age = '17';
console.log(`i am ${name}, ${age} years old`)
// 反引号可以支持变量式拼接,变量用$开头,变量名用{}包裹

//字符串中用\n换行

字符串的一些方法

  • js中,字符串可以用数组型式获取第index个字符,如string[3]
  • .length,返回字符串的长度
  • .charAt(index),返回字符串的第index个字符
  • .charCodeAt(index),返回字符串的第index个字符的编码
  • .concat('b','c'),拼接字符串,把b,c加到字符串后面
  • .indexOf(string),返回string在字符串中的index
  • lastIndexOf(string),倒着返回查找到的字符串index
  • .split()分割字符串
  • .substring(a,b) .slice(a,b),返回字符串的第a到b个字符,省略b则返回a到末尾。
  • .includes(string) ,返回布尔值,string是否在字符串内
  • .startsWith() .endsWith(),返回布尔值,判断开头结尾。
  • .repeat(int),返回字符串重复int次后的新字符串
  • .padStart(int,'char') .padEnd(int,'char') ,字符串不足int个长度,在开始/尾部用’char’填充

nullundefined

  • null值为空,不是一个全局的标识符
  • undefined 值为空,全局标识符,表示未定义
1
2
3
4
5
6
7
8
9
// == 判断值是否相等,===判断值和类型是否相等
typeof null // "object"(not "null" for legacy reasons)
typeof undefined // "undefined"
null === undefined // false
null == undefined // true
null === null //true
!null // true
isNaN(1 + null) // false1+null返回1,是一个数字,因此isNaN判断是否不是数字,返回假
isNaN(1 + undefined) // true1+undefined返回NaN,因此isNaN返回真

ES6新类型symbol

  • 一种新类型,得到一个唯一的值
  • 用于对象的属性名,可以保证不会与替他属性名产生冲突
  • 使用:let s = Symbol(); typeof s; ->"symbol",使用Symbol值定义属性 时,symbol值必须放在方括号中

ES6数据结构map set

  • map是一组键值对的结构,有非常快的查询速度
    • key值支持多种类型,按插入顺序排列
    • 创建var map = new Map()
    • .size()获取长度
    • map.set(key,value) 插入一个键值
    • map.keys() 返回所有key
    • map.values() 返回所有的val
    • map.get(key) 根据key查找返回val
    • map.clear()清空map
1
2
3
4
5
6
// 遍历map
map.forEach(
(v,k) => {
console.log(`key:${k}, value:${v}`)
}
)
  • Set是一组key的集合,存储唯一值
    • var s1 = new Set();
    • .add(value) 往集合里添加值,set会使值不重复
    • .delete(value) 删除集合里的值
    • .has(value) 返回布尔值,集合里是否有这个value
    • .size返回集合大小
    • .clear清空集合

  • 数组
    JavaScript中的数组类似于Python中的列表
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    obj.length          数组的大小

    obj.push(ele) 尾部追加元素
    obj.pop() 尾部获取一个元素
    obj.unshift(ele) 头部插入元素
    obj.shift() 头部移除元素
    obj.splice(start, deleteCount, value, ...) 插入、删除或替换数组的元素
    obj.splice(n,0,val) 指定位置插入元素
    obj.splice(n,1,val) 指定位置替换元素
    obj.splice(n,1) 指定位置删除元素
    obj.slice( ) 切片
    obj.reverse( ) 反转
    obj.join(sep) 将数组元素连接起来以构建一个字符串
    obj.concat(val,..) 连接数组
    obj.sort( ) 对数组元素进行排序

ES6的object对象

  • js对象是一种无序的集合数据类型,由若干个键值对组成

  • 对象是属性的容器,每个属性有名字和值,用k:v关系表示,逗号隔开

  • 对象是无类型的,k,v都可以自定义

  • 对象可以嵌套,但不建议太多层

  • 属性可以动态添加,所有属性都是字符串,值可以是任意类型

  • 创建:

1
2
3
4
5
6
7
8
9
10
11
12
13
var obj_a ={};

// 另一种常用方式,避免object被修改,object内的值是可以修改的
const obj_b = {};

// 使用.name方式添加和修改object内部值,或者使用["key"];[]常用于当key有特殊字符.不支持时候,如:
obj_b["class-1"] = "abc"

////////////////
obj_b.name = 'lmc';
name = obj_b.name;
name = 123
// 对象的引用不会被复制,直接修改name只会使name改变,而不会使obj_b的name属性改变
  • 原型对象prototype,是个标配对象。属性通过原型链往上查找,没有此属性会产生undifiend
  • hasOwnProperty(key) 对象中有没有这个key属性值,只会检测当前对象,不会往上找原型
  • delete obj删除对象,不涉及原型链

ES6的类数组array-like对象

  • 其实就是object和数组的混合体,兼具双方特点,未设置key则index为key
  • 声明
1
2
3
4
5
var aList = [];
typeof aList;
// "object",融合了object和数组的一个神奇的东西
aList.name = "lmc";
// 这样做是可以的,默认使用index作为key,当使用点新增数据时,添加key
  • 特性

    • 可以存储不同的数据类型的元素
    • 数组长度可变
    • 数组索引可以是数字,也可以是字符串
    • 可以多层嵌套
  • 属性

    • .length取得长度
  • 方法

    • .concat() 连接数组
    • .jonn() 将数组元素连接起来以构建字符串,默认使用,连接;可添加一个参数,指定连接符
    • .pop() 删除并返回数组的最后一个元素
    • .push(),在数组最后添加一个元素,并返回索引;等同于aList[aList.length]=obj
    • .reverse()点到数组中元素的顺序
    • .sort() 对数组元素进行排序,不加参数,以字符串方式排序,对数字无效;对数字进行排序,需要给一个排序的函数:aList.sort((a,b) => a-b);
    • .shift()删除并返回数组的第一个元素
    • .unshift(),在数组第一个元素前添加一个元素,并返回length
    • .slice()返回数组的一部分,.slice(3,8),返回第4-9个元素
    • .splice() 插入、删除或替换数组元素

JSON序列化

  • JSON.stringify(obj) 序列化
  • JSON.parse(str) 反序列化

转义

  • decodeURI( ) URl中未转义的字符
  • decodeURIComponent( ) URI组件中的未转义字符
  • encodeURI( ) URI中的转义字符
  • encodeURIComponent( ) 转义URI组件中的字符
  • escape( ) 对字符串转义
  • unescape( ) 给转义字符串解码
  • URIError 由URl的编码和解码方法抛出

条件语句

1
2
3
4
5
6
7
if(条件){
...
}else if(条件){
...
}else{
...
}
  • 三元运算符(a >b) ? "ok":"no"
    • (条件) ? 真的值:假的值

循环

  • for循环

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    a=[11,22,33,44];
    //循环数组时,循环的是索引;循环字典时,循环的是key
    for(let item in a){
    console.log(a[item]);
    }

    //循环初始值0,每次+1,大于10结束;字典不支持此种循环
    for(let i=0;i<10;i++){

    }
  • for ... of循环

    • for…of 语句创建一个循环来迭代可迭代的对象。在 ES6 中引入的 for…of 循环,以替代 for…in 和 forEach() ,并支持新的迭代协议。for…of 允许你遍历 Arrays(数组), Strings(字符串), Maps(映射), Sets(集合)等可迭代的数据结构等。
    • 语法
1
2
3
4
5
for (variable of iterable) {
statement
}
// variable:每个迭代的属性值被分配给该变量。
// iterable:一个具有可枚举属性并且可以迭代的对象。
  • for...of 更多用于特定于集合(如数组和对象,map,set等),但不包括所有对象。

  • for ...in 循环的是key,for ...of迭代的是value

  • while循环

1
2
3
4
5
6
7
8
do{
// todo
}
while(条件);

while(条件){
// todo
}
  • 刹车:break continue

ES6函数和方法

  • 简单声明
    1
    2
    3
    4
    function 函数名(参数){
    //函数体
    console.log();//控制台调试打印
    }
  • 匿名声明
1
2
3
function(){
// 函数体
}
  • 函数作为返回值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function area(w, h){
    returen w*h;
    }

    function info(w, h){
    console.log(`计算面积${w}X${h}:`);
    return area;
    }
    var a = info(4,3)(4,3);
    console.log(a);

参数

  • 默认参数

    1
    2
    3
    4
    function learnJS(func,other,verion='ES6'){
    console.log('当前版本', verion);
    }
    learnJS('aaa', 'bbb', verion='ES9')
  • rest参数(剩余参数)

    1
    2
    3
    4
    5
    6
    function sumAll(...all){
    console.log(all);
    return all.reduce(function(x,y){return x + y});
    }
    s = sumAll(1,2,3,4,5);
    console.log(s);

函数的属性和方法

  • .name,返回函数名,不论是否把这个函数赋值给变量
  • .length,返回函数的参数个数,只计形式参数,不计默认参数和rest参数
  • toString(),打印函数的内容

ES6的变量解构赋值和作用域

  • 解构赋值,把变量和值一一对应创建
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    let [a,b,c] = [1,2,3]
    let [x,,y] = [4,5,6]
    let [n,m='cc'] = ['bb'] // 默认值
    let {foo, baz} = {foo:'aaa',baz:'bbb'}
    const [a,b,c,d,e] = 'hello';
    let {length:len} = 'hello';// len 5

    // 得到返回值
    function example(){
    return [1,2,3];
    }
    let [aa,bb,cc] = example();
    aa;// 1
    bb; // 2
    cc;// 3

    // 返回对象
    function exp_obj(){
    return {
    name:'lmc',
    age:18,
    }
    }
    let {name, age} = exp_obj();
    name;// lmc
    age;// 18

函数作用域

  • 全局变量:在函数之外定义的变量,函数内部可以访问

    • 最外层函数和在最外层函数外面定义的变量拥有全局作用域
    • 所有未定义直接赋值的变量自动声明为拥有全局作用域
    • 所有window对象的属性拥有全局作用域
  • 局部变量:在函数内部,只能在函数内部访问,外部无法访问

    • 定义函数的同时,就创建了一个函数作用域
    • 内部定义的变量不能在函数外部访问
    • 嵌套的作用域变量从当前作用域往上寻找声明,找不到则报错
    • 函数执行时所在的作用域,是定义时的作用域,而不是调用时所在的作用域
  • 块级作用域

    • let声明的变量只在代码块有效
    • let声明的变量不存在变量提升
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      function f5(){
      let n = 5;
      if(true){
      let n = 10;
      }
      console.log(n);
      }
      f5();// 5
      function f10(){
      var n = 5;
      if (true){
      var n = 10;
      }
      console.log(n);
      }
      f10();// 10

this关键字

  • 直接被调用的函数,this为全局对象
  • 被某个对象调用的函数,this为当前对象

箭头函数

  • ES6允许使用=>这样的语法定义函数,参数 => 返回值
  • 支持表达式模式和语句模式
1
2
3
4
5
var f = v => v;
// 等同于
var f = function(v){
return v;
};
  • 如果箭头函数不需要参数或需要多个参数,用一个圆括号代表参数部分
1
2
3
4
5
6
7
8
9
var f = () => 5;
// 等同于
var f = function () { return 5; };

var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2){
return num1 + num2;
}
  • 如果箭头函数的代码块部分多于一条语句,就要使用大括号包裹,并且使用return返回
1
var sum = (num1, num2) => { return num1 + num2;}
  • 数组里的一些箭头函数

eval

  • JavaScript中的eval是Python中eval和exec的合集,既可以编译代码也可以获取返回值。
  • eval()
  • EvalError 执行字符串中的JavaScript代码

时间

1
2
3
4
var date = new Date();
//实例化时间对象
//date.getXXX getHours 返回小时字段
//date.setXXX

date对象参考


JavaScript面向对象

1
2
3
4
5
6
7
8
9
10
11
function foo(n){
this.name = n;//创建了一个对象的字段(属性)
/*-----------------------------*/
this.sayname = function(){
console.log(this.name);
}//创建了这个对象的方法
/*-----------------------------*/
//创建对象,this相当于python的self;
}
var obj = new foo('lmc');//实例化对象
obj.sayname();//执行类的方法
  • 上述代码中每个对象中均保存了一个相同的Func函数,从而浪费内存。使用原型和可以解决该问题:
1
2
3
4
5
6
7
8
9
10
11
12
13
function Foo (name,age) {
this.Name = name;
this.Age = age;
}
//foo的原型
Foo.prototype = {
GetInfo: function(){
return this.Name + this.Age
},
Func : function(arg){
return this.Name + arg;
}
}

定时器

1
2
3
4
<script>
//创建一个定时器
setInterval("alert(123);",5000) //第一个参数为要执行的东西,第二个参数是间隔时间(毫秒)
</script>
  • 滚动文字例子
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <div id="str">我要滚动,走了,快跑!</div>

    <script>
    function gun(){
    var e = document.getElementById('str');
    var content = e.innerText;
    var f = content.charAt(0);
    var l = content.substring(1,content.length);
    var new_content = l+f;
    e.innerText = new_content;
    }
    setInterval("gun();",500)

    </script>

ES6 promiseasync

  • promise是异步编程的一种解决方案,比传统的解决方案(回调函数和事件),更合理更强大。最早由社区提出和实现,ES6将其写进了语言标准,统一了方法,原生提供了Promise对象。
  • 所谓Promise,简单说是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。Promise提供统一的API,各种异步操作都可以用同样的方法进行处理。
  • 为异步编程提供了一种新的方式,Promise把未来将用到的值当做一等对象。

给你一个诺言,要么成功,要么失败

特点

  • promise对象状态不受外界影响
  • promise对象代表一个异步操作,有三种状态:pending(进行中) 、fulfilled(已成功) 和 rejected(已失败)。
  • 只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
  • 一旦状态从pending到fulfilled或rejected,就不会再改变,任何时候都可以得到这个结果。只要上述这两种状态发生,状态就凝固了,会一直保持这个结果,这时就称为resolved已定型
  • 如果状态已经发生,你再对promise对象添加回调函数,也会立即得到这个结果。这与事件Event不同,事件的特点是:如果你错过了它,再去监听,是得不到结果的
  • 调用resolve或reject以后,promise的使命就完成了,后续操作应放到then方法里面,而不应该直接写在resolve或reject的后面

async定义

  • Async函数定义async function foo() {}
  • Async函数表达式const foo = async function () {}
  • Async定义对象的方法let obj = {async foo() {}}
  • Async箭头函数const foo = async() => {}

##async返回Promises

  • 正常then,fulfilled;报错catch,rejected

使用await异步得到结果和错误


javascript作用域

  • python以函数作为作用域边界
  • 其他语言如C#以代码块为作用域边界,即{}

  1. JavaScript以函数为作用域
    • 在JavaScript中每个函数作为一个作用域,在外部无法访问内部作用域中的变量。
1
2
3
4
5
6
function Main(){
var innerValue = 'seven';
}
Main();
console.log(innerValue);
// 报错:Uncaught ReferenceError: innerValue is not defined
  1. 函数的作用域在函数未被调用之前已被创建
    • JavaScript的作用域在函数写好后,解释器解释即被创建,且被执行之前已经创建,日后调用函数去执行时只需要按照作用域链去寻找即可。
1
2
3
4
5
6
7
8
9
10
11
xo = 'alex';
function Func(){
var xo = "seven";
function inner(){
console.log(xo);
}
return inner;
}
var ret = Func();
ret();
// 输出结果: seven

上述代码,在函数被调用之前作用域链已经存在:

全局作用域 -> Func函数作用域 -> inner函数作用域
当执行【ret();】时,由于其代指的是inner函数,此函数的作用域链在执行之前已经被定义为:全局作用域 -> Func函数作用域 -> inner函数作用域,所以,在执行【ret();】时,会根据已经存在的作用域链去寻找变量。

  1. javascript作用域链

    • 由于JavaScript中的每个函数作为一个作用域,如果出现函数嵌套函数,则就会出现作用域链。
    • 当执行console.log(xo)时,其寻找顺序为根据作用域链从内到外的优先级寻找,如果内层没有就逐步向上找,直到没找到抛出异常。
  2. 局部变量提前声明

    • 在JavaScript中如果不创建变量,直接去使用,则报错:
    1
    2
     console.log(xxoo);
    // 报错:Uncaught ReferenceError: xxoo is not
    • JavaScript中如果创建值而不赋值,则该值为 undefined,如:JavaScript中如果创建值而不赋值,则该值为 undefined,如:
    1
    2
    3
     var xxoo;
    console.log(xxoo);
    // 输出:undefined`var` `xxoo;`
    • 在函数内如果这么写:在函数内如果这么写:
    1
    2
    3
    4
    5
    6
    7
     function Foo(){
    console.log(xo);
    var xo = 'seven';
    }

    Foo();
    // 输出:undefined
    • 在解释器解释的过程中,函数在“预编译”时函数在“预编译”时,会查询所有的局部变量并执行一个var,即提前创建
  • 百度搜索js词法分析了解详细js解析流程
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

请我喝杯咖啡吧~

支付宝
微信