前端HTML基础JS

109 阅读10分钟

前端HTML基础JS

数组操作

数组常见方法

let array = [1,2,3,4,5,6,7,8,9] 
console.log(array.length); // 8 数组长度计算是从0开始算

数组的增、删、改、查

增push(常用)、unshift(常用)、splice(常用)、concat(常用)

let array = [1,2,3];
array.push(4); 
console.log(array); // 在数组末尾增加并返回最新的数组[1,2,3,4]
array.unshift(5); 
console.log(array); // 在数组头部添加数据[5,1,2,3,4]
aray.splice(1,0,0) 
console.log(array) // 传入三个参数,分别是开始位置、0(要删除的元素数量)、插入的元素[5,0,1,2,3,4]
let arrays = array.concat(6,[7,8]) // 创建一个当前数组的副本,然后再把它的参数添加到副本末尾,最后返回这个新构建的数组,不会影响原始数组
console.log(arry) // [5,0,1,2,3,4]
console.log(arrays) // [5,0,1,2,3,4,6,7,8]

删pop(常用)、shift(常用)、splice(常用)、slice(常用)

let array = [5,0,1,2,3,4,6,7,8];
array.pop()
console.log(array);  // [5,0,1,2,3,4,6,7] pop() 方法用于删除数组的最后一项,同时减少数组的length 值,返回被删除的项
array.shift(); 
console.log(array); // [0,1,2,3,4,6,7] shift()方法用于删除数组的第一项,同时减少数组的length 值,返回被删除的项
array.splice(0,1);
console.log(array); // [1,2,3,4,6,7] 传入两个参数,分别是开始位置,删除元素的数量,返回包含删除元素的数组
let arrays = array.slice(5);
console.log(arrays) // [1,2,3,4,6] // slice() 用于创建一个包含原有数组中一个或多个元素的新数组,不会影响原始数组

改 splice()

let array =[1,2,3,4]
array.splice(1,1,9,10)
console.log(array
) // [1,9,10,3,4]传入三个参数,分别是开始位置,要删除元素的数量,要插入的任意多个元素,返回删除元素的数组,对原数组产生影响

查 indexOf() 、includes() 、find()

let arrays = [1,2,3,4,5];
let array  = array.indexOf(4);
console.log(array) //5 返回要查找的元素在数组中的位置,如果没找到则返回 -1


let arra = array.includes(4);
console.log(arra)// true 返回要查找的元素在数组中的位置,找到返回true,否则false
let people = [{name: 'lucky',age:10},{name: 'jian',age:18}];
people.find((element, index,array)=>{element.age =10} // 返回第一个匹配的元素

排序方法 reverse()、sort()

let array =[0,1,2,3,8,4]
array.reverse() // [8,4,3,2,1,0] 将数组元素方向反转
array.sort() //[0,1,2,3,4,8] 用于判断哪个值应该排在前面

转换方法 join()

let array = [0,1,2,3,4,5];
array.join('"'); // 0"1"2"3"4"5 即字符串分隔符,返回包含所有项的字符串

迭代方法 some();、every()、forEach(常用)、filter()、map(常用);

let array = [0,1,2,3,4,5];
const arr = array.some((item)=> item > 2)
console.log(arr); // true 对数组每一项都运行传入的测试函数,如果至少有1个元素返回 true ,则这个方法返回 true
const arrs = array.every((item)=> item > 2)
console.log(arrs); // false 对数组每一项都运行传入的测试函数,如果所有元素都返回 true ,则这个方法返回 true


array.forEach((item)=>{
  console.log(item) //0,1,2,3,4,5 遍历数组操作 
});
 array.map((item)=>{
console.log(item); // 0,1,2,3,4,5 遍历数组操作
})
let arry =array.filter((item)=>item>3)
console.log(arry) // 4,5 函数返回 true 的项会组成数组之后返回

字符串操作

let stringValue ="字符串字节长度为";
console.log(stringValue.length); // 7 字符串长度从1开始

增、删、改、查

增 concat() 与数组中concat一样

let stringValue ='lucky'
let stringValues = stringValue.concat('jian')
console.log(sreingValues) // lucky jian 用于将一个或多个字符串拼接成一个新字符串

删 slice()、substr()、substring()

let stringValue = 'lucky jian';
let stringS = stringValue.slice(3);
console.log(stringS, '--slice--');//ky jian 从字符串第一个删除三位
const stringV = stringValue.substr(2,6); //cky ji 保留字符位数2-6位,其余全部删除
console.log(stringV, '--substr-');
const stringVl = stringValue.substring(3,7)
console.log(stringVl, '--substring--'); // ky j 保留字符位数3-7位,其余全部删除

改 trim()、trimLeft()、trimRight()、repeat()、padStart()、padEnd()、tolowerCase()、toUpperCase()

let stringValue = ' lucky jian '
console.log(stringValue.trim();) //'lucky jian'删除前后空格
console.log(stringValue.trimLeft();) //'lucky jian '删除左边空格
console.log(stringValue.trimRight();) //' lucky jian'删除右边空格
let stringS = 'lucky '
console.log(string.repeat(2)); //lucky lucky 重复构造字符串,参数多少构造多少个
let stringV = 'lucky';
console.log(stingV.padStart(3,'*')) // ***lucky 字符串前面添加相同的值
let stringS = 'lucky';
console.log(stringS.toLowerCase()); // LUCKY大写转换
console.log(stringS.toUpperCase()); // lucky小写转换

查 chatAt()、indexOf()、startWith()、include()

let stringValue ='luckyjian'
console.log(stringValue.chatAt(2)) //c 返回给定索引位置的字符,由传给方法的整数参数指定
console.log(stringValue.indexOf('k')) // 3 从字符串开头去搜索传入的字符串,并返回位置(如果没找到,则返回 -1 )
console.log(stringValue.startWith('lucky')) //true
console.log(stringValue.startWith('kyji')) //false 适合头部字符查询
console.log(string.include('lucky')) // true
console.log(string.include('kyji')) // true 是否包含查找

转换 split()

let stringS = '1+1+1+1'
console.log(string.split('+') // [1,1,1,1] 把字符串按照指定的分割符,拆分成数组中的每一项

模板匹配方法math()、search()、replace()

let string ='a,ab,ac,ad,bc';
let value='a'
console.log(string.math(value)); //[a,ab,ac,ad] 接收一个参数,可以是一个正则表达式字符串,也可以是一个RegExp对象,返回数组
console.log(string.search(value)); // 1 可以是一个正则表达式字符串,也可以是一个RegExp对象,找到则返回匹配索引,否则返回 -1
console.log(string.replace('a','s')) //s,ab,ac,ad,bc 接收两个参数,第一个参数为匹配的内容,第二个参数为替换的元素(可用函数)

数据类型转换

let a =1; //number类型
let b ='1'; // string类型
if(a === b){
console.log(true)
} else {
console.log(false);
}

执行上面的代码,很明显执行结果为false,因为数字类型不能和字符串进行比较,但转换数据后就可以进行比较

显示转换Number()、String()、Boolean()、parselnt()

Number()

let string = '2';
console.log(Number(string)); //2 :如果可以被解析为数值,则转换为相应的数值 
let nan = '123a';
console.log(Number(string)); // NAN 如果不可以被解析为数值,返回 NaN
let string ='';
console.log(Number(string)); // 0 空字符串转为0
let is = true;
console.log(Number(is)); //1 布尔值:true 转成 1,false 转成 0
 let un;
console.log(Number(un)); // NaN undefined:转成 NaN


let object = {a:1};
console.log(Number(object )); // NaN 对象:通常转换成NaN(除了只包含单个数值的数组)

Number转换的时候是很严格的,只要有一个字符无法转成数值,整个字符串就会被转为NaN

String()

let a =1;
console.log(String(a)); // '1'  数值:转为相应的字符串
let string = 'a';
console.log(String(string)); // 'a' 字符串:转换后还是原来的值
let is =true;
console.log(String(is)); // 'true' 布尔值:true转为字符串"true",false转为字符串"false"
let un;
console.log(String(un)); // undefined undefined:转为字符串"undefined"


let no=null
console.log(String(no)); //null null:转为字符串"null"
let object ={name:1}
console.log(String(object)) // "[object Object]"
let array =[0,1,2,3]
console.log(String(array)); // "1,2,3"

可以将任意类型的值转化成字符串

Boolean()

Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true

ParseInt()

let string = '12a3';
console.log(parseLnt(string)); // 12 parseInt相比Number,就没那么严格了,parseInt函数逐个解析字符,遇到不能转换的字符就停下来

隐式转换 (==、 != 、>、<)、if、while (+、-、*、%)

'5' - '2' // 3
'5' * '2' // 10
true - 1  // 0
false - 1 // -1
'1' - 1   // 0
'5' * []    // 0
false / '5' // 0
'abc' - 1   // NaN
null + 1 // 1
undefined + 1 // NaN

拷贝

Object.assign()

const obj = {
    age: 18,
    nature: ['smart', 'good'],
    names: {
        name1: 'fx',
        name2: 'xka'
    },
    love: function () {
        console.log('fx is a great girl')
    }
}
const newObj = Object.assign({}, obj);
console.log(newObj); //

slice()

const array = ['lucky', 'jian'];
const newArray = array.slice(0);
console.log(newArray) //从第零个开始拷贝

concat()

const array = ['lucky', 'jian'];
const newArray = array.cancat();
console.log(newArray) //拷贝整个数组

扩展运算符

const array = ['lucky', 'jian'];
const newArray = [...array];
console.log(newArray) //拷贝整个数组

深拷贝_.cloneDeep()、jQuery.extend()、JSON.stringify()、手写循环递归

深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性

_.cloneDeep()

const _ = require('lodash');
const obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
const obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);// false

jQuery.extend()

const $ = require('jquery');
const obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
const obj2 = $.extend(true, {}, obj1);
console.log(obj1.b.f === obj2.b.f); // false

JSON.stringify()

const obj = {
    name: 'A',
    name1: undefined,
    name3: function() {},
    name4:  Symbol('A')
const obj2 = JSON.parse(JSON.stringify(obj));
console.log(obj2); // {name: "A"}

递归循环

function deepClone(obj, hash = new WeakMap()) {
  if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  // 可能是对象或者普通的值  如果是函数的话是不需要深拷贝
  if (typeof obj !== "object") return obj;
  // 是对象的话就要进行深拷贝
  if (hash.get(obj)) return hash.get(obj);
  let cloneObj = new obj.constructor();
  // 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
  hash.set(obj, cloneObj);
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      // 实现一个递归拷贝
      cloneObj[key] = deepClone(obj[key], hash);
    }
  }
  return cloneObj;
}

浅拷贝和深拷贝都创建出一个新的对象,但在复制对象属性的时候,行为就不一样

浅拷贝只复制属性指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存,修改对象属性会影响原对象

闭包

闭包就是一个函数对其周围状态的应用捆绑在一起,这样的组合叫做闭包

const init =()=>{
  const name ='luckyjian'; //name是被一个init创建的局部变量
  const initName = ()=>{ initName() //是一个内部函数,一个闭包
  console.log(name) //使用了父类函数声明的变量
  }
initName();
}
init();

闭包的作用额和使用场景

1、创建私有变量

2、延长变量的生命周期

      function init(x){
        console.log(x, '---5--')
        return function add(y){
          console.log(y, '---3--');
          return x+y;
        }
      }
      let numberAdd = init(5);
      console.log(numberAdd, '--numberAdd--') // 返回function为add的函数
      console.log(numberAdd(3), '---8--');

柯里化的目的在于避免频繁调用具有相同参数函数的同时,又能够轻松的重用

function makeCounter() {
    var privateCounter = 0
    function changeBy(val) {
        privateCounter += val
    }
    return {
        increment: function() {
            changeBy(1)
        },
        decrement: function() {
            changeBy(-1)
        },
        value: function() {
            return privateCounter
        }
    }
}
var Counter1 = makeCounter()
var Counter2 = makeCounter()
console.log("Counter1.value():", Counter1.value())  //Counter1.value(): 0
Counter1.increment()
Counter1.increment()
console.log("Counter1.value():", Counter1.value())  //Counter1.value(): 2
Counter2.decrement()
console.log("Counter2.value():", Counter2.value())  //Counter1.value(): -1
    </script>

两个计数器 Counter1 和 Counter2 是如何维护它们各自的独立性的。每个闭包都是引用各自的词法作用域内的变量 privateCounter。

注意事项:不是某些特定任务需要使用闭包,在其它函数中创建函数是不明智的,因为闭包在处理速度和内存消耗方面对脚本性能具有负面影响

this的指向

this关键志在JavaScript中的表现略有不同,在严格模式和非严格模式之间也会存在差异

let a= 10;
let obj= {
name:'luckyjian',
age: 16
}
function fn(){
this = obj
console.log(this.a); erro //执行会出错
}
fn();

this在函数的执行过程中,this一旦确认就不能进行更改

this的绑定关系

默认绑定

let name = 'luckyjian';
function fn(){
return this.name; 
}
console.log(fn); //luckyjian

非严格模式:调用函数的对象在游览器中位window,因此this指向window,所以输出luckyjian

严格模式:不能将全局对象用于默认绑定,this会绑定到undefined,只有函数运行在非严格模式下,默认绑定才能绑定到全局对象

function fn (){
  console.log(this.name);
}
let obj ={};
obj.name ='luckyjian'
obj.m = fn;
onj.fn(); // lukyjian

尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象

new绑定

let object= new fn();
function fn(){
this.x=1;
}
obj.x

new关键字改变了this的指向

new过程遇到return一个对象,此时this指向为返回的对象

let object= new fn();
function fn(){
return {};
}
obj.x // undefinde

显示修改

let a =0;
function fn (){
console.log(this.a);
}
let obj = {};
obj.a =1;
obj.m= fn
obj.m.app(obj); // 1

apply()、call()、bind()是函数的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象。因此,这时this指的就是这第一个参数

箭头函数

const obj = {
  sayThis: () => {
    console.log(this);
  }
};


obj.sayThis(); // window 因为 JavaScript 没有块作用域,所以在定义 sayThis 的时候,里面的 this 就绑到 window 上去了
const globalSay = obj.sayThis;
globalSay(); // window 浏览器中的 global 对象

箭头函数的this能够在编译的时候就确定了this的指向,箭头函数不能作为构建函数

优先级关系

new绑定====》显式绑定====》隐式绑定 ===》默认绑定