Jason Lee
首页
  • 学习笔记

    • 常用资源
    • html&css
    • webpack
    • vue2.x
    • vue3
    • typescript入门
    • 工程化实践
  • css
  • javascript
  • es6常问
  • 手写代码
  • 错误监控
  • webpack
  • vue框架
  • 浏览器相关
  • 计算机网络
  • 数据结构和算法
  • 学习笔记
工具
首页
  • 学习笔记

    • 常用资源
    • html&css
    • webpack
    • vue2.x
    • vue3
    • typescript入门
    • 工程化实践
  • css
  • javascript
  • es6常问
  • 手写代码
  • 错误监控
  • webpack
  • vue框架
  • 浏览器相关
  • 计算机网络
  • 数据结构和算法
  • 学习笔记
工具
  • css
  • javascript
    • 7 种原始类型和 1 种引用类型
    • null 和 undefined 区别
    • 判断数据类型
    • 类型转换
    • 运算符
    • 值的比较
    • 面向对象
      • 对象的创建&构造函数
      • new 命令
      • this
    • 原型、原型链
    • F.prototype
    • JavaScript 执行机制
    • 作用域
    • 作用域链
    • 闭包
    • 事件简介
    • Promise,async/await
    • 操作节点 API 总结
  • 错误监控
  • ES6常问
  • 手写代码
  • webpack
  • vue框架
  • 浏览器相关
  • 计算机网络
  • 数据结构和算法
  • 设计模式
  • interview
jason lee
2021-09-02
目录

javascript

# 7 种原始类型和 1 种引用类型

  • number 任何类型的数字(原始类型)
  • bigint 任意长度的整数 (原始类型)尾部的 "n" 表示这是一个 BigInt 类型
  • string 字符串 (原始类型)
  • boolean true 和 false (原始类型)
  • null 未知的值 (原始类型)
  • undefined 未定义的值 (原始类型)
  • symbol 唯一的标识符 (原始类型)
  • object 更复杂的数据结构(引用类型)

原始类型和引用类型区别:

JS 中,所有的变量都是保存在栈内存中的。

基本数据类型:

基本数据类型的值,直接保存在栈内存中。值与值之间是独立存在,修改一个变量不会影响其他的变量。

引用数据类型:

对象是保存到堆内存中的。每创建一个新的对象,就会在堆内存中开辟出一个新的空间;而变量保存了对象的内存地址(对象的引用),保存在栈内存当中。如果两个变量保存了同一个对象的引用,当一个通过一个变量修改属性时,另一个也会受到影响。

# null 和 undefined 区别

  • null 专门用来定义一个空对象(例如:let a = null)。如果你想定义一个变量用来保存引用类型,但是还没想好放什么内容,这个时候,可以在初始化时将其设置为 null。
  • undefined:变量已声明未赋值时、变量未声明(未定义)时、函数无返回值时、调用函数时,未传参
  • 任何数据类型和 undefined 运算都是 NaN;(10 + null = 10)
  • 任何值和 null 运算,null 可看做 0 运算。(10 + undefined = NaN)

# 判断数据类型

  • typeof(返回值是 string 类型)
typeof 100; // "number"
typeof 10n; // "bigint"
typeof "jason"; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof Symbol("id"); // "symbol"
typeof null; // "object" 这是 JavaScript 编程语言的一个错误,实际上它并不是一个 object
typeof console; // "function"
  • instanceof
  • Object.prototype.toString.call()
  • constructor

# 类型转换

三种情况:字符串转换、数字型转换、布尔转换

# 运算符

加法 +,减法 -,乘法 *,除法 /,取余 %,求幂 **

















 
 




console.log(6 + 2); // 8
console.log(6 - 2); // 4
console.log(6 * 2); // 12
console.log(6 / 2); // 3
console.log(6 % 4); // 2
console.log(6 ** 2); // 36

var a = 1,
  b = 1;
console.log(++a); // 2,前置运算符返回最新值
console.log(b++); // 1,后置运算符返回旧值

// 转布尔
console.log(Boolean(undefined)); // false
console.log(Boolean(null)); // // false
// 转数字
console.log(+undefined); // NaN
console.log(+null); // // 0
// 逗号运算符ti
let a = (1 + 2, 3 + 4); // 每个语句都运行,只有最后的语句的结果会被返回
console.log(a); // 7(3 + 4 的结果)

提示

做运算的时候,把运算元(参数)转换成数字再继续运算

# 值的比较

  • 大于 / 小于:a > b,a < b。
  • 大于等于 / 小于等于:a >= b,a <= b。
  • 检查两个值的相等:a == b,请注意双等号 == 表示相等性检查,而单等号 a = b 表示赋值。
  • 检查两个值不相等。不相等在数学中的符号是 ≠,但在 JavaScript 中写成 a != b。
console.log(undefined == null); // true
console.log(undefined === null); // false
console.log(!undefined === !null); // true 一元运算符比===优先级高
console.log(+undefined === +null); // false 一元运算符比===优先级高

# 面向对象

# 对象的创建&构造函数

  • 方法一:对象字面量
var obj = {};
  • 方法二:对象字面量
/*
 * 使用工厂方法创建对象
 *  通过该方法可以大批量的创建对象
 */
function createPerson(name, age, gender) {
  //创建一个新的对象
  var obj = new Object();
  //向对象中添加属性
  obj.name = name;
  obj.age = age;
  obj.gender = gender;
  obj.sayName = function() {
    alert(this.name);
  };
  //将新的对象返回
  return obj;
}

var obj2 = createPerson("lee", 28, "男");
var obj3 = createPerson("rui", 27, "男");
var obj4 = createPerson("gna", 18, "女");
  • 方法三:利用构造函数
// 创建一个构造函数
function Student(name) {
  this.name = name; //this指的是当前对象实例
  this.sayHi = function() {
    console.log(this.name);
  };
}
//利用构造函数自定义对象
var stu1 = new Student("jason");
console.log(stu1);

var stu2 = new Student("lrg");
console.log(stu2);

构造函数:是一种特殊的函数,主要用来创建和初始化对象,也就是为对象的成员变量赋初始值。它与 new 一起使用才有意义。构造函数的创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写。

# new 命令

new 命令的作用:就是执行构造函数,返回一个实例对象。

  • 创建一个空对象,作为将要返回的对象实例。
  • 将这个空对象的原型,指向构造函数的 prototype 属性。
  • 将这个空对象赋值给函数内部的 this 关键字。
  • 开始执行构造函数内部的代码。
function _new(constructor, ...rest) {
  var context = Object.create(constructor.prototype); //
  var result = constructor.apply(context, rest);
  var isObj = typeof result === "object" && result !== null;
  return isObj ? result : context;
}
// 测试
function Person(name) {
  this.name = name;
}
var person = _new(Person, "jason");
console.log(person.name);

new.target: 函数内部可以使用 new.target 属性。如果当前函数是 new 命令调用,new.target 指向当前函数,否则为 undefined

function fn() {
  if (!new.target) {
    throw new Error("请使用new调用");
  }
}

# this

  • 从JavaScript执行上下文视角讲this: 执行上下文中包含了变量环境、词法环境、外部环境,和this, this 是和执行上下文绑定的,也就是说每个执行上下文中都有一个 this。

  • 从使用场合视角讲this:

    • 1.以函数的形式(包括普通函数、定时器函数、立即执行函数)调用时,this 的指向永远都是 window。比如fun();相当于window.fun();

    • 2.以方法的形式调用时,this 指向调用方法的那个对象

    • 3.以构造函数的形式调用时,this 指向实例对象

    • 4.以事件绑定函数的形式调用时,this 指向绑定事件的对象

    • 5.使用 call 和 apply 调用时,this 指向指定的那个对象 (call,apply 的第一个参数)

  • 注意点:

    • 避免多层 this
    • 避免数组处理方法中的 this
    • 避免回调函数中的 this

# 原型、原型链

JavaScript 通过构造函数生成实例对象,但是有一个缺点。同一个构造函数生成多个实例对象,无法共享属性,造成对系统资源的浪费。要解决这个问题,就需要原型对象, 原型对象上的所有属性和方法,都能被实例对象共享。JavaScript 规定,每个函数都有一个prototype属性,指向一个对象。这个对象就是原型。构造函数在生成实例的时候, 该prototype属性会自动成为实例对象的原型。

JavaScript 规定,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个“原型链”

在 JavaScript 中,对象有一个特殊的隐藏属性 [[Prototype]],它要么为 null,要么就是对另一个对象的引用。该对象被称为“原型”。 原型链:原型就是一个对象,也有一个特殊的隐藏属性 [[Prototype]],它要么为 null,要么就是对另一个对象的引用。通过[[Prototype]] 隐藏属性连接成一条线。

var obj = {
  name: "jason",
};
var obj1 = Object.create(null);
console.log(obj, "obj");
console.log(obj1, "obj1");

图片加载失败

属性 [[Prototype]] 是内部的而且是隐藏的,设置方式:__proto__

let animal = {
  eats: true,
};
let rabbit = {
  jumps: true,
};

rabbit.__proto__ = animal; // (*)

// 现在这两个属性我们都能在 rabbit 中找到:
alert(rabbit.eats); // true (**)
alert(rabbit.jumps); // true

图片加载失败

# F.prototype

如果 F.prototype 是一个对象,那么 new 操作符会使用它为新对象设置 [[Prototype]]。 这里的 F.prototype 指的是 F 的一个名为 "prototype" 的常规属性。这听起来与“原型”这个术语很类似,但这里我们实际上指的是具有该名字的常规属性。 下面是一个例子:

let animal = {
  eats: true,
};

function Rabbit(name) {
  this.name = name;
}

Rabbit.prototype = animal;

let rabbit = new Rabbit("White Rabbit"); //  rabbit.__proto__ == animal

alert(rabbit.eats); // true

设置 Rabbit.prototype = animal 的字面意思是:“当创建了一个 new Rabbit 时,把它的 [[Prototype]] 赋值为 animal”。

  • F.prototype 属性(不要把它与 [[Prototype]] 弄混了)在 new F 被调用时为新对象的 [[Prototype]] 赋值。
  • F.prototype 的值要么是一个对象,要么就是 null:其他值都不起作用。
  • "prototype" 属性仅在设置了一个构造函数(constructor function),并通过 new 调用时,才具有这种特殊的影响。

# JavaScript 执行机制

分为编译阶段和执行阶段

输入一段代码,经过编译后,会生成两部分内容:执行上下文(Execution context)和可执行代码。

执行上下文:是 JavaScript 执行一段代码时的运行环境,比如调用一个函数,就会进入这个函数的执行上下文,确定该函数在执行期间用到的诸如 this、变量、对象以及函数等。 在执行上下文中存在一个变量环境的对象(Viriable Environment),该对象中保存了变量提升的内容

showName();
console.log(myname);
var myname = "jason";
function showName() {
  console.log("函数showName被执行");
}
// 我们可以一行一行来分析上述代码:

// 1. 第1行和第2行,由于这两行代码不是声明操作,所以JavaScript引擎不会做任何处理;
// 2. 第3行,由于这行是经过var声明的,因此JavaScript引擎将在环境对象中创建一个名为myname的属性,并使用undefined对其初始化;
// 3. 第4行,JavaScript引擎发现了一个通过function定义的函数,所以它将函数定义存储到堆(HEAP)中,并在环境对象中创建一个showName的属性,然后将该属性值指向堆中函数的位置,这样就生成了变量环境对象。

# 作用域

  • 概念:通俗来讲,作用域是一个变量或函数的作用范围。作用域在函数定义时,就已经确定了。
  • 目的:为了提高程序的可靠性,同时减少命名冲突。
  • 分类:
    • 全局作用域:作用于整个 script 标签内部,或者作用域一个独立的 JS 文件。
    • 函数作用域(局部作用域):作用于函数内的代码环境。
  • 作用域的访问关系:在内部作用域中可以访问到外部作用域的变量,在外部作用域中无法访问到内部作用域的变量。

# 作用域链

作用域链:内部函数访问外部函数的变量,采用的是链式查找的方式来决定取哪个值,这种结构称之为作用域链。查找时,采用的是就近原则。

一般情况下,变量取值到创建这个变量的函数的作用域中取值。但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。 JS 中的作用域链主要用于解析变量的值。 如果没有这个,在不同的作用域内定义了许多变量,JS 很难为变量选择某个值。

var name = "jason";
function fn() {
  // 外部函数
  var name = "lee";
  function func() {
    // 内部函数
    console.log(name);
  }
  func();
}
fn();

# 闭包

  • 概念:指有权访问另一个函数作用域中变量的函数。
  • 作用:
    • 延伸变量的作用范围
    • 封装私有方法
  • 缺点: 造成内存泄漏

# 事件简介

事件的三要素: 事件源、事件、事件驱动程序。 网页上弹出一个广告,我点击右上角的 X,广告就关闭了。这件事情里,事件源是:X。事件是:onclick。事件驱动程序是:广告关闭了。

绑定事件的两种方式/DOM 事件的级别:

  • DOM0 的写法:onclick
element.onclick = function() {};
  • DOM2 的写法:addEventListener

事件传播的三个阶段:事件捕获、事件冒泡和事件目标。

  • 事件捕获阶段:事件从祖先元素往子元素查找(DOM 树结构),直到捕获到事件目标 target。在这个过程中,默认情况下,事件相应的监听函数是不会被触发的。

  • 事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。

  • 事件冒泡阶段:事件从事件目标 target 开始,从子元素往冒泡祖先元素冒泡,直到页面的最上一级标签。

阻止冒泡: event.stopPropagation(); 事件委托:就是把一个元素响应事件(click、keydown......)的函数委托到另一个元素。

# Promise,async/await

promise 是 js 中的一个对象,用于生成可能在将来产生结果的值。 值可以是已解析的值,也可以是说明为什么未解析该值的原因。

promise 可以有三种状态:

  • pending:初始状态,既不是成功也不是失败
  • fulfilled:意味着操作完全成功
  • rejected:意味着操作失败

一个等待状态的 promise 对象能够成功后返回一个值,也能失败后带回一个错误 当这两种情况发生的时候,处理函数会排队执行通过 then 方法会被调用

# 操作节点 API 总结

  • 查找节点

    • document.getElementById :根据 ID 查找元素,大小写敏感,如果有多个结果,只返回第一个
    • document.getElementsByClassName :根据类名查找元素,多个类名用空格分隔,返回一个 HTMLCollection 。
    • document.getElementsByTagName :根据标签查找元素, * 表示查询所有标签,返回一个 HTMLCollection 。
    • document.getElementsByName :根据元素的 name 属性查找,返回一个 NodeList 。
    • document.querySelector :返回单个 Node,如果匹配到多个结果,只返回第一个。
    • document.querySelectorAll :返回一个 NodeList。
    • document.forms :获取当前页面所有 form,返回一个 HTMLCollection ;
  • 创建节点

createElement 创建元素 createTextNode 创建文本节点 cloneNode 克隆一个节点 createDocumentFragment 创建文档碎片,主要是用来存储临时节点,大量操作 DOM 时用它可以大大提升性能

  • 修改节点

appendChild insertBefore removeChild replaceChild

css
错误监控

← css 错误监控→

Theme by Vdoing | Copyright © 2019-2022 jason lee | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式