前端JavaScript基础(二)

165 阅读4分钟

本篇文章仅为个人学习理解,通过工作、书籍、博客等资料整理,如有错误或遗漏欢迎指出。


前端学习JavaScript基础篇(一)

接上文

作用域

可访问变量的集合。

  1. 一些与作用域相关的概念

宿主环境:是由外壳程序决定(web浏览器、nodeJS、桌面应用、嵌入式等)只要能提供js引擎执行的环境都可称之为外壳程序。

执行环境:JavaScript代码都是在执行环境中执行的,包括了全局环境(浏览器中为window)与局部环境(函数运行环境)。

预解析:以var、function关键字声明的变量与函数会提前解析到内存中。

console.log(a) // a输出为undefined 并不会报错。
var a = 1     // 执行到这句时进行赋值
// let 声明的变量不会预解析,在执行let语句之前的区域被称为这个变量的暂时性死区。
  1. 作用域链

当函数在运行时会隐式创建一个集合对象,这个集合保存了所有可见范围内的变量和对象。这个集合对象就称为作用域链。

  1. 闭包

嵌套函数,内部函数引用外部函数的变量,当我们在外部去调用内部函数时就会产生闭包。 这里要清晰一个概念:词法作用域。

词法作用域是在函数声明阶段会提前生成一个集合,这个集合包括了函数内部所引用到的全部变量。

function fn1 () {
  var a = 1;
  function fn2 (){
    a++;
    console.log(a)
  }
  return fn2
}
let test = fn1()
test();  // 输出2 此时内部函数的词法作用域会挂载到全局环境中,而这个类集合(词法作用域)会常驻内存。
test();  // 输出3 从词法作用域中查询变量 并执行返回结果
iv.es6块级作用域
// {} 称为块级作用域
if () {} 
for () {}
{}
function () {} //局部作用域
// let const 声明的变量只在块级作用域中生效
// 而var 则不会在块级作用域中

对象

人们所研究的一切事物都可以看作为对象,类是对象的抽象,对象是类的实例。

  1. 创建对象
// 字面量的方式
let people = {'name': 'mike'}; // 在js中对象是以Json形式呈现
// 构造函数的方式
function Fun () {}
let fn = new Fun();
let obj = new Object();
people.name // -> 'mike' 用 . 属性名来取值
people['name'] // -> 'mike' 用[属性名/算式/函数/]来取值
// 一些简写
let animal = {name: '动物'} // 如果属性名不加引号系统会默认添加
let size = 20;
let obj = {size} // 这种情况会将对象中当`size`当成变量处理,并且属性名为size值为其变量的值
// 对象的解构赋值
let {name, age} = {name: 'Tom', age: 20} // 变量name为右边对象的值,age同理

读取属性过程:先从自身对象寻找,如果没有再从其原型链__proto__中寻找属性,依次向上寻找,不存在返回undefined。

let obj = {};
// 删除这个对象
obj = null;
  1. 原型对象与原型链

prototype是原型对象,它存在于函数中,是函数对象(除箭头函数)的一个属性,实例对象通过其构造函数的prorotype 继承其构造函数中定义的属性及方法。

__proto__是所有对象中的属性,用来继承其构造函数身上的属性及方法,通过上述对象中读取属性的方式,从而构成了原型链。

Javascript原型链

图中比较特殊的是构造函数Function,在JavaScript中所有的函数对象都是通过Function来创建的,包括它本身。

如图中所示在原型链的尽头Object.prototype它的__proto__指向的是 null

  1. 封装与继承
function People (name, age) {
  this.name = name;
  this.age = age
}
People.prototype.study = function () {
  console.log(this.name + '正在学习。')
}
// 等...
let tom = new People('tom', 20)
tom.study() // 输出'tom正在学习'
// es6中class语法糖 本质同上
class People {
  constructor(name) { // 构造函数
    this.name = name;
  }
  study() {   // 同People.prototype.study = function(){};
    console.log(this.name + '学习呢')
  }
}

上述代码中tom为函数People的实例对象,继承了People的study方法,我们称People函数为tom对象的构造函数

new 关键字的大致过程:

  1. 创建一个空对象。
  2. 让这个空对象去执行这个构造函数。
  3. 这个对象的__proto__指向构造函数的prototype属性。 this指针:在普通函数中,谁去调用函数,this就指向谁。在es6箭头函数中this的指向是其运行环境决定的。
function abc() {
  console.log(this)
}
abc();// 在浏览器非严格模式下 输出为window对象 可以看作 window.abc()
// 严格模式则为undefined
// 并不是undefined调用了abc函数,而是在严格模式中this禁止指向window而返回undefined
let a = new abc() // 输出abc的实例对象a 参考new过程的第二步