《你不知道的JS上》笔记

JS是编译型言语

编译发生在代码实行前几微秒,简朴来讲就是js在实行前要举行编译,编译历程发生在代码实行前几玄妙,以至更短。

编译的步骤

  1. 词法剖析
    以var a = 2 为例,词法剖析会将其分红三个有意义的代码块即词法单位。
  2. 语法剖析
    将词法单位组合天生代表了顺序语法的组织的树,即笼统语法书(AST)。
  3. 代码天生
    将AST天生可实行的代码。行将AST转化成一组机械指令。​​​

LHS RHS

假如查找的目标是对变量举行赋值,那末就会运用 LHS 查询;假如目标是猎取变量的值,就会运用 RHS 查询。

词法作用域

决定于你在写代码时的块级作用域

优化

依赖于词法的静态剖析

eval with 会竖立新的作用域

在词法剖析阶段,没法晓得eval with会对作用域做如何的修正,此时引擎不再对作用域举行任何优化

函数作用域

函数声明 函数表达式

辨别函数声明和表达式最简朴的要领是看 function 关键字出现在声明中的位
置(不仅仅是一行代码,而是全部声明中的位置)。假如 function 是声明中
的第一个词,那末就是一个函数声明,不然就是一个函数表达式。

let

  1. 隐式的天生块级作用域
  2. 不存在变量提拔

提拔

缘由

变量(包含函数在内)的一切声明都邑优先实行,只要声明自身会提拔,而赋值或其他运转逻辑会留在原位置

历程

这意味着不管作用域中的声明出现在什么地方,都将在代码自身被实行前起首举行处置惩罚。
可以将这个历程抽象地设想成一切的声明(变量和函数)都邑被“挪动”到各自作用域的
最顶端,这个历程被称为提拔。
声明自身会被提拔,而包含函数表达式的赋值在内的赋值操纵并不会提拔。

闭包

定义

当函数可以记着或接见地点的词法作用域,实时是被作用域外挪用,就产生了闭包

模块

  1. 当代模块机制
  2. 将来的模块机制

关于this

绑定时刻点

是在函数运转时绑定的,而非定义时。它的上下文取决于函数挪用时的种种前提,和在那里定义的没有关联,只取决于函数的挪用体式格局。

绑定历程

当函数被挪用时,会竖立一个实行上下文,在这个上下文里包含了函数在那里没挪用(挪用栈),挪用函数的要领,参数等。this作为实行上下文的一个属性,可以在函数实行的历程当中用到。

绑定范例

  1. 默许绑定
    即绑定到全局,严厉形式下回绑定到undefined。

    function foo() {
      console.log( this.a );
    }
    var a = 2;
    (function(){
      "use strict";
       foo(); // 2
    })()
  2. 隐式绑定
    即绑定到最顶层(或近来挪用对象)上

    function fun() {
      console.log(this.a)
    }
    var obj2 = {
      a: 3,
     fun: fun,
    }
    var obj1 = {
      a: 2,
      obj2: obj2,
    }
    obj1.obj2.fun() // 3
  3. 显式绑定
    即用call或apply手动举行绑定
  4. bind要领完成
  5. new绑定(组织函数)

    1. 不存在
      实在在js中不存在组织函数,我们所说的组织函数实在就是一般的函数,它只是用new被“组织挪用”罢了。
    2. new发生了什么?

      1. 竖立(或者说组织)一个全新的对象。
      2. 这个新对象会被实行[[原型]]衔接。
      3. 这个新对象会绑定到函数挪用的this。
      4. 假如函数没有返回其他对象,那末new表达式中的函数挪用会自动返回这个新对象。
  6. 箭头函数 =>

对象

内置对象

基本范例在须要的时刻(比方说猎取长度),会被引擎默许转成内置对象,从而举行要领的挪用。
基本范例并非继续自内置对象​

    var strPrimitive = "I am a string";
    typeof strPrimitive; // "string"
    strPrimitive instanceof String; // false
    var strObject = new String( "I am a string" );
    typeof strObject; // "object"
    strObject instanceof String; // true
    Object.prototype.toString.call( strObject ); // [object String] 

null

typeof null === Object; 

道理是如许的,差别的对象在底层都示意为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判
断为 object 范例,null 的二进制示意是全 0,天然前三位也是 0,所以实行 typeof 时会返回“object”

拷贝

  1. 浅拷贝
    Object.assign({}, obj)
  2. 深拷贝
    JSON.stringify

属性描述符

getOwnPropertyDescriptor(myObj, 'a')
defineProperty
Object.defineProperty(myObj, 'a', {
  value: 2,            
  ​writable: true,
  configurable: true, 
  enumerable: true 
​})

Getter 、Setter

var obj = {
  get a() {
    return this._a_
  },
  set a(val) {
   this._a_ = val * 5
  }
}
obj.a = 10
console.log(obj.a) // 50
​
var obj2 = {}
Object.defineProperty(obj2, 'a', {
  get: function() {
    return this._a_
  },
  set: function(val) {
    this._a_ = val * 2
  }
})
obj2.a = 15
console.log(obj2.a) // 30

存在性

  1. in
    ‘a’ in obj1 会搜检obj及其原型链上是不是有’a’
  2. hasOwnProperty
    不会搜检原型链,假如须要可以Object.prototype.hasOwnProperty.call(myObj, ‘a’)

原型(prototype)

constructor

返回实例对象O的组织函数(的援用)。任何一个prototype对象都有一个constructor属性,指向它的组织函数,每一个实例也有一个constructor属性,默许挪用prototype对象的constructor属性​
比方

function Test() {
  this.name = 'test'
}
var test = new Test()
console.log(test.constructor === Test) // true

类constructor

组织函数 constructor 是用于竖立和初始化类中竖立的一个对象的一种特别要领.

class Polygon {
    constructor() {
        this.name = "Polygon";
    }
}
class Square extends Polygon {
    constructor() {
        super();
    }
}
class Rectangle {}
Object.setPrototypeOf(Square.prototype, Rectangle.prototype);
console.log(Object.getPrototypeOf(Square.prototype) === Polygon.prototype); //false
console.log(Object.getPrototypeOf(Square.prototype) === Rectangle.prototype); //true
let newInstance = new Square();
console.log(newInstance.name); //Polygon​

proto

实例对象__proto__指向天生改对象的组织函数的原型
比方

|function Test() {
  this.name = 'test'
}
Test.prototype = {
  color: 'red'
}
var test = new Test()
console.log(test.__proto__ === Test.prototype) // true
console.log(test.__proto__)

Object.create

var foo = {
something: function() {
  console.log( "Tell me something good..." );
}
};
var bar = Object.create( foo ); 
bar.something(); // Tell me something good...
Object.create(..) 会竖立一个新对象(bar)并把它关联到我们指定的对象(foo)

如许 我们就可以充分发挥 [[Prototype]]
机制的威力(托付)而且防止不必要的贫苦
(比方使 用 new 的组织函数挪用会天生 .prototype 和 .constructor 援用)。

继续

原型继续

瑕玷
实例的属性都邑指向同一个援用
完成

function Parent() {
  this.names = [1, 2, 3]
}
function Child() {
  
}
Child.prototype = new Parent()
var child1 = new Child()
var child2 = new Child()
child1.names.push(4)
console.log(child1.names) // [1,2, 3,4]
console.log(child2.names) // [1,2, 3,4]

借用组织函数

完成

function Parent() {
  this.names = [1, 2, 3]
  this.getName = function () {
    console.log(this.name)
  }
}
function Child() {
  Parent.call(this)
}
var child1 = new Child()
var child2 = new Child()
child1.names.push(4)
console.log(child1.names)
console.log(child2.names)

瑕玷
每一个子实例都邑实例化要领一次,内存爆炸

组合继续(最经常使用)

完成

function Parent() {
  this.names = [1, 2, 3]
}
Parent.prototype.getName = function () {
  console.log(this.names)
}
function Child() {
  Parent.call(this)
}
Child.prototype = new Parent()
var child1 = new Child()
var child2 = new Child()
child1.names.push(4)
child1.getName()
child2.getName()

瑕玷

  1. 子类实例上有一份父类的属性,两者反复形成内存糟蹋
  2. 父类的组织函数被挪用了两次​

寄生式组合继续

完成

function Parent() {
  this.names = [1, 2, 3]
}
Parent.prototype.getName = function () {
  console.log(this.names)
}
function Child() {
  Parent.call(this)
}
Child.prototype = Object.create(Parent.prototype)
var child1 = new Child()
var child2 = new Child()
child1.names.push(4)
child1.getName()
child2.getName()

长处
属性不会再原型链上反复

行动托付

js中的继续实在就是在对象间竖立关联关联,而行动托付就是竖立这类关联关联的纽带。

(“原型”)面向对象作风

function Foo(who) {
  this.me = who;
}
Foo.prototype.identify = function () {
  return "I am" + this.me;
};
function Bar(who) {
  Foo.call(this,who);
}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.speak = function () {
  alert("Hello," + this.identify() + '.');
};
var b1 = new Bar("b1");
var b2 = new Bar("b2");
b1.speak();
b2.speak();

对象关联作风

Foo = {
  init:function (who) {
    this.me = who;
  },
  identify:function () {
    return "I am" + this.name
  }
};
Bar = Object.create(Foo);
Bar.speak = function () {
  alert("hello," + this.identify() + '.');
};
var b3 = Object.create(Bar);
b3.init("b3");
var b4 = Object.create(Bar);
b4.init("b4");
b1.speak();
b2.speak();

    原文作者:wupengyu
    原文地址: https://segmentfault.com/a/1190000016297759
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞