基础篇

PlumliilAbout 16 min

基础篇

面向对象

Object qriented programming

在面向对象的程序开发思想中,每一个对象都是功能中心,具有明确分工

面向对象变成具有灵活,代码可复用,容易维护和开发的特点,更适合多人合作的大型软件项目

面向对象的作用

封装 继承 多态

面向对象是把事物分解为一个个对象,然后有对象之间分工合作

举个例子,把大象放进冰箱面向对象做法

先找出对象,并写出这些对象的功能

1.大象为对象

进去

2.冰箱对象

打开

关闭

3.使用大象和冰箱的功能

面向对象是以对象功能来划分问题,而不是步骤

面向对象和面向过程的优缺点

面向过程

优点:性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用面向过程

缺点:不如面向对象易维护,易复用,易扩展

面向对象优缺点相反,耦合高,更灵活,易维护

面向过程程序就像蛋炒饭

面向对象程序就像盖浇饭

语言基础

标识符

所谓标识符就是变量函数属性或者函数参数的名称

规则:

  • ​ 第一个标识符必须是一个字符,下划线或者美元符号
  • ​ 剩下的字符可以是字母下划线美元符号或者是数字
  • ​ 关键字,保留字,true,false 和 null 不能作为标识符

保留字与关键字

ECMA-262 描述了一组保留字,这些关键字有特殊用处,按照规定,保留的关键字不能作为标识符或者属性名

变量

EMCAScript 的变量是松散类型,意思是可以用于保存任何类型的值

声明风格及最佳实践:不使用或少用 var const 优先,let 次之

var

  • 作用域在函数内部,离开函数,var 声明的变量无效

  • 在函数内定义变量省略 var 操作符,可以定义一个全局变量

function text() {
  var message = "hello world"; // 局部变量
}
text();
console.log(message); //出错 !

function text() {
  message = "hello world"; // 全局变量
}
text();
console.log(message); // 'hello world
  • 存在变量提升

使用关键字声明的变量自动提升到函数作用域顶部

function fn() {
  console.log(age);
  var age = 18;
}
fn(); //undefined 输出undefind并不报错 代码等价于

function fn() {
  var age;
  console.log(age);
  age = 18;
}
fn(); // undefined

let & const:

  • let 和 const 的作用域为块级作用域(块级作用域﹝函数作用域)
if(true){
	var message='hello world';
    console.log(message); //'hello world'
}
console.log(message); // 'hello world'

if(true)(
	let message='hello world';
    console.log(message); //'hello world'
)
console.log(message); //ReferenceError:message没有定义
  • let 和 const 声明的变量不存在变量提升
console.log(age);
let age = 18; //ReferenceError:message没有定义
  • 其中 const 声明的变量不可修改(不允许重复声明)

数据类型

ECMAScript 有六种简单的数据类型(也称原始类型)还有一种复杂的数据类型 object
简单数据类型说明
undefined表示值未定义
boolean表示值为布尔值(其他数据类型的值都有相应布尔值的等价形式)
string表示值为字符串
number表示值为数值
null表示值为空值(逻辑上讲 null 值表示一个空对象指针,给 typeof 传入 null 时会返回 object)
symbol表示值为符号
bigInt表示大于 2^53 的整数。而在Javascript中,Number 基本类型可以精确表示的最大整数是 2^53。BigInt 可以表示任意大的整数。
复杂数据类型说明
object表示值为对象(而不是函数)

其中 typeof 操作符可以确定变量的任意数据类型如

let message = "hello world";
console.log(typeof message); //'string'
console.log(typeof 10); //'number'

操作符

一元操作符,位操作符,布尔操作符,乘性操作符,指数操作符,加性操作符,关系操作符,相等操作符,条件操作符,赋值操作符,逗号操作符

操作符说明
i++,i--,++i,--i
~,&,|,^,<<,>>,>>>
!,&&,||
*,/
**
+,-
>,<,>=,<=
,!=,=,!==
variable = boolean_expression?true_value:false_value
=

变量的声明(弱类型)

1.typeof 验证变量类型

let a = "lyh";
console.log(a);
console.log(typeof a); // string
a = 99;
console.log(typeof a); // number
a = {};
console.log(typeof a); // objecct

​ 声明是开辟空间,赋值是放入内容

2.体验解析过程与变量提升

​ 解析是把所有代码解析,也存在变量提升(不好)

function fn() {
  if (false) {
    var web = "lyh.com";
  } else {
    console.log(web);
  }
}
fn(); //undefind

​ var 声明的变量存在变量提升

​ let const 声明的变量不存在

3.let const 暂时性死区

​ let const 声明的变量不存在变量提升

声明语句必须放到使用之前

4.var let const 共同点

​ 函数中可以访问到外部全局变量

​ 内部声明后为私有

​ 使用时先找局部变量,如果没有使用全局变量

​ 作用域链 就近原则

var web = "lyh.com";
function show() {
  var web = "lyh";
  console.log(web); // lyh
  function run() {
    var web = "run---web";
    console.log(web);
  }
  run(); // run---web
  console.log(web); // lyh
}
show(); // lyh
console.log(web); // lyh.com
6.全局污染

​ 可以使用严格模式来避免全局污染

​ use strict

7.块作用域的先进特性

​ 声明变量是优先使用 let

var i = 99;
for (let i = 0; i < 5; i++) {
  console.log(i);
}
console.log(i);

8.const 声明

​ 定义固定常量,不能更改(同一个作用域)

​ 引用类型的对象数组可以改变

const web = "lyh.com";
function show() {
  const web = "web.com";
  console.log(web);
}
show();

9.window 全局对象污染与重复声明

​ var 可能导致全局污染

​ let 不会导致(不会改变 window 对象)

var screenLeft = 88;
console.log(window.screenLeft); // 88
let screenLeft = 88;
console.log(window.screenLeft); //xxxx
console.log(screenLeft); //88

​ let const 不可以重复声明(统一作用域)

let web = "ls";
let web = "zs";
console.log(web);
// Identifier 'web' has already been declared

10.object.freeze 冻结变量

// object.freeze冻结变量
"use strict";
const HOST = {
  url: "https://lyh.com",
  post: 8080,
};
Object.freeze(HOST);
HOST.post = 3000;
console.log(HOST);

11.标量与引用特性的传值与传址

// 地址也改变,创建新的内存地址,针对小数据(两个内存空间)
let a = 1;
let b = a;
console.log(a, b);
b = 3;
console.log(a, b);
// 地址没有改变,不创建新的内存地址,针对大数据(一个内存空间)
let e = { name: "zs" };
let f = e;
console.log(e, f);
f.name = "ls";
console.log(e, f);

12.null undefined

​ 没有值为 undefined

// null undefined
let config = null; // 引用类型 {}
let web = undefined; // 基本类型 ''
console.log(config);
console.log(web);

function show(name) {
  console.log(name);
}
console.log(show());

13.严格模式

​ 避免未声明变量使用

​ 避免保留字的使用

​ 严格模式作用域为从当前作用域向下查找

"use strict";

var pub = "ww";
console.log(pub); //Uncaught SyntaxError: Unexpected strict mode reserved word

var web = "ls";
function run() {
  web = "zs";
}
run();
console.log(web); //Uncaught ReferenceError: web is not defined

function show() {
  "use strict";
  function handle() {
    webadd = "zs.com";
  }
  handle();
}
function na() {
  site = "啦啦啦";
}
show(); //Uncaught ReferenceError: webadd is not defined

let { name, url } = { name: "zs", url: "zs.com" };
console.log(name, url);

运算符和流程控制

1.赋值与算术运算符

​ 取余%

2.一元运算符的前置与后置

​ ++i:先自增,i++:先运算 --同理

let n = 1;
let f = 2;
let d = f + n++;
console.log(d);

3.比较运算符注意事项

​ 不同类型之间比较会转换类型

true let a = 1, b = 2, c = 1, d = '1';
 console.log(a < b);//true
 console.log(a > b);//false
 console.log(a == b);//false
 console.log(a == c);//true
 console.log(a == d);//true
 console.log(b >= 2);//true
<body>
  <input type="text" name="age" />
  <span id="msg"></span>
  <script>
    let inp=document.querySelector('[name="age"]');
    let span=document.querySelector('#msg');
    inp.addEventListener('keyup',function(){
        span.innerHTML=this.value>=90?'年龄不能超过90':'';
    });
  </script>
</body>

4.逻辑运算符

let a = 1,
  b = 1;
if (a == 1 && b == 1) {
  // 全为真
  console.log("ab全为1");
}
if (a == 1 || b == 2) {
  // 一个满足条件就成立
  console.log("有一个为1");
}
<body>
  <input type="text" name="password" id="" />
  <input type="text" name="config_password" />
  <span name="msg"></span>
  <script>
    function query(name) {
      return document.querySelector(`[name='${name}'`);
    }
    let inputs = document.querySelectorAll(
      '[name="password"],[name="config_password"]'
    );
    console.log(inputs);
    [...inputs].map((item) => {
      item.addEventListener("keyup", function () {
        msg = "";
        if (
          query("password").value != query("config_password").value ||
          query("password").value.length < 5
        ) {
          msg = "两次密码不一致或密码长度小于5位";
        }
        query("msg").innerHTML = msg;
      });
    });
  </script>
</body>

5.短路与运算的妙用

let a = 1,
  b = 0;
if (a || b) {
  console.log(11);
}

let c = 6,
  d = 0;
let f = c || d;
console.log(f);

let sex = prompt("输入") || "保密";
console.log(sex);

function star(num) {
  return "*".repeat(num || 1);
}
console.log(star());

6.网站协议接收验证

trim()

trim() 方法用于删除字符串的头尾空白符,空白符包括:空格、制表符 tab、换行符等其他空白符等。

trim() 方法不会改变原始字符串。

<body>
    <form action="" id="form">
        用户名:<input type="text" name="user">
        <hr>
        <input type="checkbox" name="copyright" id=""> 接收协议
        <hr>
        <button>提交</button>
    </form>
    <script>
        function query(el){
            return document.querySelector(el);
        }
        query('#form').addEventListener('submit',function(){
            let user=query('[name="user"]').value.trim();
            let copyright=query('[name="copyright"]').checked;
            console.log(user.length);
            if(!user||copyright===false){
                console.log('请提交协议并添加用户名');
            }
            event.preventDefault();
        })
    </script>
</body>

7.if else 判断密码长度

<body>
  <form action="" id="form">
    <input type="password" name="password" />
    <span id="msg"></span>
  </form>
  <script>
    function query(el) {
      return document.querySelector(el);
    }
    query('[name="password"]').addEventListener("keyup", function () {
      let length = this.value.length;
      let msg = "";
      if (length > 10) {
        msg = "密码无敌安全";
      } else if (length > 6) {
        msg = "密码强度适中";
      } else {
        msg = "密码强度较弱";
      }
      query("#msg").innerHTML = msg;
    });
  </script>
</body>

8.三元表达式

// 可以作为用户自定义创建对象来使用
function div(options = {}) {
  let div = document.createElement("div");
  div.style.width = options.width ? options.width : "100px";
  div.style.height = options.height ? options.height : "100px";
  div.style.backgroundColor = options.bgcolor ? options.bgcolor : "pink";
  document.body.appendChild(div);
}
div({ width: "300px", height: "400px", bgcolor: "blue" });

数组

shift

shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。

注意: 此方法改变数组的长度!

提示: 移除数组末尾的元素可以使用 pop()open in new window 方法。

let arr1 = ["l", "y"];
let arr2 = ["h", 1, 2, 3];
arr1.push(...arr2);
// console.table(arr1);
function range(begin, end) {
  const arr = [];
  for (let i = begin; i <= end; i++) {
    arr.push(i);
  }
  return arr;
}
// console.table(range(1,50))

const arr3 = ["hdcms", "houdunren"];
let arr4 = arr3.shift();
console.log(arr4);
// const arr4 = arr3.unshift('后盾人');
console.table(arr3);

fill

fill() 方法用于将一个固定值替换数组的元素。

console.log(Array(5).fill("lyh"));
console.log([1, 2, 3, 4].fill("l", 1, 3));

splice 和 slice

let arr = [1, 2, 3, 4, 5];
let arr1 = arr.slice();
arr1.splice(arr1.length, 0, "li");
console.table(arr1);

数组移动函数

function move(array, from, to) {
  if (from < 0 || to >= array.length) {
    console.error("参数错误");
    return;
  }
  const newArray = [...array];
  let item = newArray.splice(from, 1);
  console.log(item);
  newArray.splice(to, 0, item[0]);
  console.table(newArray);
  return newArray;
}
let array = [1, 2, 3, 4];
move(array, 1, 2);

清空数组

let arr = [1, 2, 3, 4, 5, 6];
let arr1 = arr;
arr.length = 0;
console.log(arr);

数组的拆分与合并

let arr = ["hdcms", "houdunren"];
let hd = [1, 2, 3, 4];
let cms = ["shop", "cms"];
let str = "hdcms,houdunren";
console.log(str.split(","));
// arr=arr.concat(hd,cms);
arr = [...arr, ...hd, ...cms];
console.table(arr);
// Array.copyWithin(复制到的位置,复制起始位置,复制终止位置(不包括))
console.log(hd.copyWithin(2, 0, 1));

数组的查找

let arr = [1, 2, 3, 4, 2];
// indexOf:从左开始查找
// lastIndexOf:从右开始查找
// includes:数组总含有这个字符串,已经查找到
console.log(arr.indexOf(2));
console.log(arr.lastIndexOf(2));

includes 方法

let arr = [1, 2, 3, 4, 5, 6, 7];
const includes = (array, find) => {
  for (const value of array) {
    if (value === find) return true;
  }
  return false;
};
console.log(includes(arr, 3));

find 和 findindex

// let arr = [1, 2, 3, 4, 5, 6, 78];
// let res=arr.find(function(item){
//     // return item=200;
//     // console.log(item);
//     // return item=200;
//     return item==200;
// })
// console.log(res);

// find查找对象,返回查询到的数据
// findIndex返回对象所在的位置
let lessons = [{ name: "js" }, { name: "css" }, { name: "html" }];
let status = lessons.find((item) => {
  return (item.name = "css");
});
console.log(status);

find 原型方法的实现

function find(array, callback) {
  for (const value of array) {
    if (callback(value)) return value;
  }
  return undefined;
}
let arr = [1, 2, 3, 4, 5, 6, 7, 8];
console.log(
  find(arr, function (item) {
    return item == 300;
  })
);

数组排序

let arr = [1, 5, 7, 3, 4, 8];
// sort()里边值为1正序,-1倒序
arr = arr.sort((a, b) => {
  // a-b
  // -1从小到大
  // 1从大到小
  return a - b;
});
console.table(arr);
let cart = [
  { name: "iphone", price: 12000 },
  { name: "imac", price: 18000 },
  { name: "ipad", price: 3200 },
];
cart = cart.sort(function (a, b) {
  return a.price - b.price;
});
console.table(cart);

数组循环操作

let lessons = [
  { title: "flex", category: "css" },
  { title: "grid", category: "css" },
  { title: "盒子", category: "css" },
];
// for (let i = 0; i < lessons.length; i++) {
//     lessons[i].title = `LYH${lessons[i].title}`
// }
// 引用类型改变原来数组
for (const value of lessons) {
  value.title = `LYH${value.title}`;
}
console.table(lessons);
let arr = [1, 2, 3];
// 值类型不会改变乱来数组
for (const value of arr) {
  value == 10;
}
console.table(arr);

foreach 循环

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .disable {
        color: #ddd;
      }
    </style>
  </head>
  <body>
    <ul>
      <li>1</li>
      <li>2</li>
    </ul>
    <script>
      let lis = document.querySelectorAll("li");
      lis.forEach((item) => {
        item.addEventListener("click", function () {
          this.classList.toggle("disable");
        });
      });
      let lessons = [
        { title: "flex", category: "css" },
        { title: "grid", category: "css" },
        { title: "盒子", category: "css" },
      ];
      lessons.forEach((item, index, lessons) => {
        // substr 截断字符串
        item.title = item.title.substr(0, 2);
      });
      console.table(lessons);
    </script>
  </body>
</html>

iterator 迭代器方法玩转数组

let arr = ["hdcms", "houdunren"];

for (const value of arr.values()) {
  console.log(value);
}
for (const keys of arr.keys()) {
  console.log(keys);
}

// entries() 方法返回一个数组的迭代对象,该对象包含数组的键值对(key / value) 。
// 迭代对象中数组的索引值作为 key, 数组元素作为 value。
let entries = arr.entries();
let { done, value } = entries.next();
console.log(done, value);
// keys() 方法用于从数组创建一个包含数组键的可迭代对象。
// 如果对象是数组返回 true,否则返回 false。
// 获取索引
// let keys = arr.keys();
// let { value, done } = keys.next();
// 获取值
// let values = arr.values();
// let { value, done } = values.next();
// while(({value,done}=values.next())&&done===false){
//     console.log(value);
// }
// console.log(value, done);

every,some

every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
every() 方法使用指定函数检测数组中的所有元素:
如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。
some() 方法会依次执行数组的每个元素:
如果有一个元素满足条件,则表达式返回 true, 剩余的元素不会再执行检测。
<body>
  <input type="text" name="title" />
  <span></span>
  <script>
    let keywords = ["php", "js"];
    let title = document.querySelector('[name="title');
    title.addEventListener("keyup", function () {
      const res2 = keywords.some((keyword) => {
        return this.value.indexOf(keyword) != -1;
      });
      if (res2 === false) {
        document.querySelector("span").innerHTML =
          "必须包含" + keywords.join(",") + "关键词";
      } else {
        document.querySelector("span").innerHTML = "";
      }
    });

    let user = [
      { name: "lisi", js: 89 },
      { name: "zhangsan", js: 99 },
      { name: "wangwu", js: 80 },
    ];
    // every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
    // every() 方法使用指定函数检测数组中的所有元素:
    // 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
    // 如果所有元素都满足条件,则返回 true
    const res = user.every((item) => {
      return item.js >= 60;
    });
    console.log(res ? "学生全部及格" : "有学生未及格");
    // let arr = ['hdcms', 'houdunren'];
    // let arr.every((item, index, arr) => {
    //     console.log(arr);
    //     return true;
    // })

    // some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。
    // some() 方法会依次执行数组的每个元素:
    // 如果有一个元素满足条件,则表达式返回true, 剩余的元素不会再执行检测。
    // 如果没有满足条件的元素,则返回false。
    let arr = ["hdcms", "houdunren"];
    let res1 = arr.some((value, index, arr) => {
      console.log(value);
      return false;
    });
    console.log(res1);
  </script>
</body>

filter

filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

  • filter() 不会对空数组进行检测。
  • filter() 不会改变原始数组。
// let arr = ['php', 'js'];
let user = [
  { name: "lisi", js: 89 },
  { name: "zhangsan", js: 99 },
  { name: "wangwu", js: 80 },
  { name: "zhaoliu", js: 92 },
  { name: "tianqi", js: 95 },
];
let newuser = user.filter((value, index, arr) => {
  return value.js >= 90;
});
console.table(newuser);

过滤函数

let arr = [1, 2, 3, 4];
function filter(array, callback) {
  let newarr = [];
  for (const value of array) {
    if (callback(value) === true) {
      newarr.push(value);
    }
  }
  console.log(newarr);
  return newarr;
}
filter(arr, function (value) {
  return value > 2;
});

map 映射数组与引用类型处理技巧

map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
注意: map() 不会对空数组进行检测。
注意: map() 不会改变原始数组。
语法
array.map(function(currentValue,index,arr), thisValue)
参数说明
参数描述
function(currentValue, index,arr)必须。函数,数组中的每个元素都会执行这个函数 函数参数: 参数描述currentValue必须。当前元素的值index可选。当前元素的索引值arr可选。当前元素属于的数组对象
thisValue可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值。 如果省略了 thisValue,或者传入 null、undefined,那么回调函数的 this 为全局对象。
// map
// map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
// map() 方法按照原始数组元素顺序依次处理元素。
// 注意: map() 不会对空数组进行检测。
// 注意: map() 不会改变原始数组。

let lessons = [
  { title: "flex", category: "css" },
  { title: "grid", category: "css" },
  { title: "盒子", category: "css" },
];
let lessons_click = lessons.map((value) => {
  return {
    title: value.title,
    category: value.category,
    click: 100,
  };
});
console.log(lessons);
console.log(lessons_click);
let arr = ["hdms", "houdunren"];
let hd = arr.map((value, index, arr) => {
  value = `后盾人-${value}`;
  return value;
});
console.log(arr);
console.log("-----------------------------");
console.log(hd);

reduce

  • reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。

  • reduce() 可以作为一个高阶函数,用于函数的 compose。

  • 注意: reduce() 对于空数组是不会执行回调函数的。

语法
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)

参数

参数描述
function(total,currentValue, index,arr)必需。用于执行每个数组元素的函数。 函数参数:参数描述total必需。初始值, 或者计算结束后的返回值。currentValue必需。当前元素currentIndex可选。当前元素的索引arr可选。当前元素所属的数组对象。
initialValue可选。传递给函数的初始值
// let arr=[1,2,3,4,5,6];
// arr.reduce((pre,value,index,arr)=>{
//     console.log(pre,value);
//     return 99;
// });
// // console.log('-------------------');
// arr.reduce((pre,value,index,arr)=>{
//     console.warn(pre,value);
//     return 99;
// },0)
let arr = [1, 2, 3, 4, 10, 1, 2, 1];
function arrayCount(array, item) {
  return array.reduce((total, cur) => {
    total += item == cur ? 1 : 0;
    total = total + (item == cur ? 1 : 0);
    return total;
  }, 0);
}
console.log(arrayCount(arr, 1));
function arrayMax(array) {
  return array.reduce((pre, cur) => {
    return pre > cur ? pre : cur;
  }, 0);
}
console.log(arrayMax(arr));

样例:字体效果

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      body {
        width: 100vh;
        height: 100vh;
        display: flex;
        justify-content: center;
        align-items: center;
        background-color: #34495e;
      }
      div {
        font-size: 4em;
        text-transform: uppercase;
        color: #9b59b6;
      }
      div > span {
        display: inline-block;
        position: relative;
      }
      .color {
        animation-name: color;
        animation-duration: 1s;
        animation-iteration-count: 2;
        animation-timing-function: linear;
        animation-direction: alternate;
      }
      @keyframes color {
        50% {
          color: #f1c40f;
          transform: scale(1.5);
        }
        100% {
          color: #e74c3c;
          transform: scale(0.5);
        }
      }
    </style>
  </head>
  <body>
    <div>lyh.wslyh</div>
    <script>
      const div = document.querySelector("div");
      console.log(...div.textContent);
      [...div.textContent].reduce((pre, cur, index) => {
        console.log(pre, cur, index);
        pre == index && (div.innerHTML = "");
        let span = document.createElement("span");
        span.innerHTML = cur;
        div.appendChild(span);
        span.addEventListener("mouseover", function () {
          this.classList.add("color");
        });
        span.addEventListener("animationend", function () {
          this.classList.remove("color");
        });
      }, 0);
    </script>
  </body>
</html>