javascript总结

148 阅读10分钟

1、三个输出一个输入

 // 1
 alert('你好!')
 // 2
 console.log('控制台输出...');
 // 3
 document.write('页面输出...')
 // 4
 prompt('请输入...')

2、变量命名规范

严格区分大小写;

不能以数字开头;

不能是关键字/保留字;

变量名必须有意义;

遵守驼峰命名法。

3、let、const与var的区别

let和const是ES6新增的声明变量的关键词,之前声明变量的关键词是var。

1.var定义的变量,可以预解析,提前调用的结果是undefined,而let、const定义的变量不能预解析,否则会报错。

2.var定义的变量,变量名称可以重复,效果是重复赋值,而let、const定义的变量不能重复,否则会报错。

3.var定义的变量作用域是全局/局部作用域,而let、const定义的变量如果在{}中则只能在{}中调用。

4.在循环语句中var定义的循环变量和使用let定义的循环变量,执行原理和执行效果不同。const定义的变量存储的数据数值不能改变,也就是const定义的变量,不能重复赋值。

4、javaScript数据类型

js的数据类型分为两种:原始类型(即基本数据类型)和对象类型(即引用数据类型)。

基本数据类型:undefined(未定义)、null(空的)、number(数字)、boolean(布尔值)、string(字符串)、Symbol(符号);

引用数据类型:object(对象)、array(数组)、function(函数)、date(时间)等。

5、检测数据类型的7种方法

1、typeof 检测一些基本的数据类型

2、A instanceof B 检测当前实例是否隶属于某个类

3、constructor 构造函数

4、hasOwnporperty 检测当前属性是否为对象的私有属性

5、is Array 判断是否为数组

6、valueOf 可以看到数据的原始值

7、Object.portotype.toString 原型方法

6、数据类型转换

Number():可以把任意值转换成数字,如果要转换的字符串中有不是数字的值,则会返回NaN

parseInt(string,radix):解析一个字符串并返回指定基数的十进制整数,radix是2-36之间的整数,表示被解析字符串的基数。

parseFloat(string):解析一个参数并返回一个浮点数

隐式转换:+  - *  % 

toString():转换为字符串,null,undefined不能调用

7、运算符

一元运算符

// 前置++ 
let i =3
console.log(++i + 8)
// 后置++
console.log(i++ + 9)
// 前置++是自身先加1再参与运算,后置++是先参与运算,后加1.到了另一边再加1

比较运算符

console.log(3>5);     false
console.log(3>=3);    true
console.log(2=='2');  true
console.log(3==='3'); false
console.log(3!==5);   true
// NaN不等于任何值,包括他自身

逻辑运算符

// 见假即假
// console.log(true && true); true
// console.log(true && false); false
// console.log(3<5 && 6<2); false

// 见真即真
// console.log(true || false);true
// console.log(false || false);false
// console.log(3>5 || 4===4);true

// 取反 假即真 真即假
// console.log(!true);false
// console.log(!false);true
// console.log(3>5);false

三元运算符

// 条件 ? 条件为true执行代码 : 条件为false执行的代码
// 用户输入2个数,在控制台输出最大的数
let num1 = prompt('请输入第一个数')
let num2 = prompt('请输入第二个数')
// 取值操作
let max = num1 > num2 ? num1 : num2
console.log(`最大的数是${max}`);

8、if判断语句

单分支语句

true执行代码
false不执行代码
if (true){
alert('你真棒')
}

双分支语句

let year = prompt('请输入年份')
// 双分支语句
if(year % 4 === 0 && year % 100 !== 0 || year % 400 === 0){
alert('闰年')
}else{
alert('平年')
}

多分支语句

let score = +prompt('请输入成绩')
if(score > 90){
alert('国家栋梁')
}else if(score > 70){
alert('中')
}else if(score > 60){
alert('不赖')
}else{
alert('废材')
}

9、 switch语句

根据输入的年龄,弹窗用户喜欢的内容
let love = prompt('请输入您的年龄')
switch(love) {
case '10':
alert('女人')
break
case '20':
alert('少妇')
break
case '30':
alert('熟女')
break
case '40':
alert('萝莉')
break
default:
alert('肾虚了')
}

10、循环

循环有:for循环、while循环、do while循环。

for(起始值,终止条件,变化量){

重复执行的代码

}

while循环

// 变量的起始值
let jin =1
// i <= 3 终止条件
while(jin <= 3){
// 每循环一次,去看条件,条件为true,继续循环,条件为false,循环结束
document.write(`我是第${jin}次循环<br>`)
// 变量的变化值
jin++
}

for循环

 // 输出1-100岁
 for(let i = 1; i <= 10; i++){
     document.write(`今年${i}岁了<br>`)
 }

双层for循环

// 九九乘法表
for(let j = 1; j <= 9; j++){
    // 里层循环控制每一行星星的个数
    for(let i = 1; i <= j; i++){
        // 规律是j和i是自增的,1,2,3,4.....9
        document.write(`<span>${i} * ${j} = ${i*j}</span> `)
    }
    document.write('<br>')
}

跳过本次循环

for(let i = 1; i <= 5; i++){
  if(i === 3){
      continue // 跳过本次循环
  }
  document.write(`这是第${i}循环<br>`)
  }

结束当前循环

for (let j = 1; j <= 5; j++){
   if(j === 3){
       break   // 不再执行循环
   }
   console.log(`这是第${j}循环`);
   }

11、数组常用方法

 arr.push('pink') // 向数组的末尾添加新内容
 arr.pop('pink') // 删除数组的最后一项
 arr.unshift('blue') // 向数组首位添加新内容
 arr.shift('blue') // 删除数组的第一项
 slice()按照条件查找出其中的部分内容
 arr.splice(1,1,'blook') //对数组进行增删改
 const a = arr.join(" === ")  // 用指定的分隔符将数组每一项拼接为字符串
 const b = jin.concat(arr) // 用于连接两个或多个数组,返回的是一个新数组
 let c = arr.indexOf('yewool')  // 检测当前值在数组中第一次出现的位置索引
lastIndexOf()检测当前值在数组中最后一次出现的位置索引
incIudes()判断一个数组是否包含一个指定的值
arr.sort() // 对数组的元素进行排序(默认是从小到大来排序 并且是根据字符串来排序的)
arr.reverse() // 把数组倒过来排列
arr.forEach((value,index,arr) =>{}) // 循环遍历数组每一项;没有返回值,会改变原数组
const d = arr.map((value,index,arr)=>{}) // 同上;有返回值,不会改变原数组
const n =  arr.filter((value,index,arr)=>{}) // 参数同上,作用过滤,不会改变原数组
  // find()根据条件查找第一个满足条件的元素;
  // find()和filter()的区别,就是一个返回第一个,另一个返回所有;
  console.log([111,222,333,444].find(item => item  %2 == 0));
  console.log([111,222,333,444].filter(item => item  %2 == 0));

  // findIndex()根据条件查找第一个满足条件的元素的索引值
  console.log([111,222,333,444,].findIndex(item => item  %2 == 0));

  // every() 是否每一项都满足条件;有一项不满足就返回false
  console.log([111,222,333,444,].every(item => item  %2 == 0));

  // some()是否存在一项都满足条件
  console.log([111,222,333,444,].some(item => item  %2 == 0));

12、字符串常用方法

        // substring(): 截取字符串
        console.log('abcdef' .substr(1,3)); //截取多少个
        console.log('abcdef' .substring(1,3)); //截取从哪里到哪里(包左不包右)
        // startsWith(): 是否以某个字符串为开始
        console.log('abcdef' .startsWith('abc'));
        // endsWith(): s是否以某个字符串为结束
        console.log('abcdef' .endsWith('def'));
        // replace():替换
        console.log('abcdef' .replace('cd','123'));
        // match(): 匹配
        console.log('abcdef' .match(/aaa/));

        // 1.slice(开始索引,结束索引):截取字符串-数组也支持;
        console.log('abcdef' .slice(1,3)); // 截取从哪里到哪里(包左不包右)
        // 2.split():切割字符串为数组;
        console.log('张三&李四&王五' .split('&'));
        // 3.includes(): 是否包含某个字符串
        console.log('abcdef' .includes('cd'));
        // 4.toUpperCase(): 转换大写
        console.log('abcdef' .toUpperCase());
        // 5.toLowerCase(): 转换小写
        console.log('abcdef' .toLowerCase());
        // 6.indexOf():查询某个字符串在调用者字符串中的索引值
        console.log('abcdef' .indexOf('cd'));

12、函数

函数的形参和实参

        function hanshu(形参1,形参2) {
            console.log();
        }
        // 调用函数的时候,实参会赋值给形参
        hanshu(实参1,实参2)

函数表达式

       // 匿名函数
       let fn= function(){
            console.log('土豆');
        }
        fn()
        
       // 具名函数
       function dog() {
            console.log('西红柿');  
        }
        dog()

13、内置对象

image.png

14、作用域与作用域链

作用域(scope)规定了变量能够被访问的“范围”,离开了这个“范围”变量便不能被访问,作用域分为全局作用域和局部作用域。

全局作用域

在整个script或者一个js文件里定义的变量,就是全局作用域,函数内部也可以访问。

局部作用域

局部作用域分为函数作用域和块级作用域。

在函数内部声明的变量只能在函数内部被访问,外部无法直接访问。

在 JavaScript 中使用 {} 包裹的代码称为代码块,代码块内部声明的变量外部将【有可能】无法被访问。

作用域链

作用域链就是变量的逐级查找机制,遵循的原则就是就近原则

15、闭包

简单理解: 闭包 = 内层函数 + 外层函数的变量

作用:扩展局部变量的作用范围

16、变量提升与函数提升

通过var定义的变量,在定义语句之前就可以访问到;变量的声明会提升到函数的顶部,变量的赋值并不会,值为undefined。

通过function声明的函数,在之前就可以调用;函数[表达式]不会进行变量提升,只有函数声明形式才可以,值为函数定义对象。

17、arguments、剩余参数、展开运算符

arguments在JS中译作参数,只有在函数中才存在,是一个伪数组。

剩余参数和arguments类似,也是接收每一次调用函数的实参数组。剩余参数是一个真数组,可以接收所有,也可以接收一部分

扩展运算符/展开运算符,把一个数组中的内容,展开变成参数序列。剩余参数是把参数序列赋值给一个数组,而扩展运算符是把数组中元素展开变成参数序列让某个函数使用。

写到实参位置的...,就是展开运算符;写到形参位置的...就是剩余参数。

18、箭头函数

        // 箭头函数和普通函数中的this不一样
        // 所以有的时候使用箭头函数,有的时候使用匿名函数

        // 1.箭头函数的基本语法
        const fn1 = () => {
            console.log('我是函数fn1');
        }
        //调用
        fn1()
        
        // 2.如果只有一个参数可以省略小括号
        const fn2 = a => {
            return a * a
        }
        console.log(fn2(3));

        // 3.如果只有一行代码,不需要返回值,可以省略大括号
        const fn3 = (a,b) => a + b
        console.log(fn3(2,2));

        // 4.返回的如果是一个对象类型,需要用 () 包裹
        const fn4 = username => ({username:username})
        console.log(fn4('张三'));

箭头函数与普通函数的区别:

1.箭头函数没有arguments,获取动态的箭头函数参数,只能使用剩余参数。

2.箭头函数没有自己的this,它的this是继承而来,所以箭头函数的this指向取决于父级环境。

19、数组解构和对象解构

数组解构就是把数组中的元素,取出来赋值给某一些变量。

对象解构类似数组的解构,只不过数组有序,对象无序。所以,解构对象的时候,要求变量和属性名一一对应;

两者的形参都有三个,分别是值/下标/当前数组

21、new做的四件事

1.new会帮我们开辟内存空间,装载新的实例

2.new会把这个构造函数中的this,指向实例对象;

3.new会帮我们执行构造函数,绑定属性和方法;

4.new会帮我们返回当前的实例对象;

22、实例成员和静态成员

        // 实例成员就是实例对象拥有的属性和方法;
        // 静态成员就是构造函数拥有的属性和方法
        //     实例成员只能实例对象调用,定义到构造函数里面
        //     静态成员只能构造函数调用,定义到构造函数上面

        // 1.实例成员 
        function Student(uname,age){
            this.uname = uname;
            this.age = age;
            this.sayHi = function(){
                console.log('大家好!');
            }
        }

        // 2.静态成员
        Student.gender = '男';
        Student.eat = function(){
            console.log('吃的多,有力气!');
        }

        // 实例成员只能该实例对象调用
        let s1 = new Student('张三',18);
        console.log(s1.uname,s1.age,s1.sayHi);
        console.log(s1.gender,s1.eat); // undefined

        // 静态成员只能构造函数调用
        console.log(Student.gender,Student.eat);

23、Object中三个静态方法

        // object中三个静态成员
        const obj = {name: '张三',age: 18, gender:'男'};

        // 1.Object.keys() 获取对象中的所有属性组成的数组
        let arr1 = Object.keys(obj);
        console.log(arr1);

        // 2.Object.values() 获取对象中的所有值组成的数组
        let arr2 = Object.values(obj)
        console.log(arr2);

        // 3.Object.assign() 赋值对象中的各种属性
        //  o1里面和o2重复会被覆盖,没有重复的值,会保留
        //  o2不会受到影响,还是原值.
        let o1 = {name: '李四',gender: '男'};
        let o2 = {name: '张三',age: 18};
        console.log(o1);
        Object.assign(o1,o2)
        console.log(o1);
        console.log(o2);

25、伪数组转真数组

        // 1.Array.from();静态方法
        let divs = document.querySelectorAll('div');
        console.log(divs);
        let arr1 = Array.from(divs);
        console.log(arr1);

        // 2.展开运算符;
        let arr2 = [...divs];
        console.log(arr2);

27、保留两位小数

       // 有时候要保留两位有效数字(四舍五入保留)
        console.log((0.01*50) .toFixed(2));
        console.log((100) .toFixed(2));

30、面向对象和面向过程

面向对象是让对象帮我们完成某个需求,面向过程是一步一步完成某个需求.

应用场景:大型和超大型项目(困难)用面向对象,简单小就用面向过程.

未来场景:我们程序员只是使用对象,不常封装对象

31、原型对象和对象原型以及原型链

原型对象prototype,对象原型_proto_。

32、forin与forof

1.(功能不同) forin是遍历数组下标,forof是遍历数组元素

2.(原型的属性) for-in会遍历原型中的属性,for-of不会

3.(数据类型) 遍历数组用for-of,遍历对象用for-in.

33、深拷贝与浅拷贝

深拷贝就是对象的值,无论简单还是复杂类型,拷贝完毕后,修改一个另一个都不会被影响。

浅拷贝可以解决对象赋值一个被修改另一个也同时被修改的问题。复杂类型,浅拷贝还是解决不了被修改的问题

34、递归

递归就是函数自己调用自己。

35、call、apply、bind

call、apply、bind都是用来改变this指向

36、防抖和节流

防抖和节流都是单位时间内,减少触发某个逻辑;

1.防抖, 单位时间内多次触发,以最后一次为准; (回城 - 取消 - 回城)

2.节流, 单位时间内多次触发,以第一次为基准; ( 技能冷却)