Giter Site home page Giter Site logo

notebook's People

Contributors

rainy934 avatar

Stargazers

 avatar

notebook's Issues

《你不知道的javascript》关键字

LHS&RHS (ReferenceError, TypeError)

词法作用域 ,遮蔽效应,作用域查找&对象访问规则

eval作用在当前作用域, new Function;欺骗词法作用域,优化手段失效,得不偿失

click 事件形成闭包,let显示设置块级作用域,避免内存泄漏

【2-1】关于this

this

JS中this很难理解它的绑定,那我们为什么还需要用到它呢,可以不用么?

this的作用简述

在执行代码时候,比如说函数中的需要取某个上下文的变量,一般来说我们是通过某种方式首先获取到这个上下文对象,然后可以取到变量;常见的可以通过两种方式取上下文对象:

  • 函数中通过参数显式传入
  • 函数中this默认绑定的上下文对象

在代码复杂度较大的情况下, 显式传入方式会导致代码很乱,很难维护

排除误解

  • this和词法作用域无关,this 的绑定和函数声明的位置没有任何关系

this是什么

this 是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件。this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方式、传入的参数等信息。this 就是这个记录的一个属性,会在函数执行的过程中用到。 ——《你不知道的JS》

调用位置

  • 函数的 this 是在调用时被绑定的,完全取决于函数的调用位置(也就是函数的调用方法)。
    调用位置就是函数被执行的时候所处的位置

绑定规则

  • 默认绑定 无法应用其他绑定规则的时候使用的默认规则

  • 隐式绑定 person.name() 方法调用位置存在上下文对象,this绑定person对象

  • 显式绑定 name.call(person) 方法通过call,apply 等方法调用,显式传入上下文对象

  • new绑定 new Person() 执行时方法中的this被绑定为一个新对象,这个对象prototype会链接Person的原型

绑定例外

显示绑定 call,apply等方法传入null,undefined等值,会被忽略,而不会取绑定到this

箭头函数不应用以上绑定规则

箭头函数不使用 this 的四种标准规则,而是根据外层(函数或者全局)作用域来决定 this。 ——《你不知道的JS》

web缓存类型

http 网络服务缓存

  • 资源服务器, 一般包括压缩包,图片等, 内容不会改变的东西,可强制缓存。
  • web服务器缓存配置要结合具体应用缓存方案来具体设置, 例如, index.html协商缓存, 资源文件强制缓存等;
  • 强制缓存,expires, control-cahce。
  • 协商缓存, Etag, Last-modify 缓存一般返回304。

【1-1】作用域

什么是作用域?

一种程序设计语言必然会使用到变量,而优秀的变量的存储和访问的逻辑设计可以使得语言执行效率有很大提升,JS中的变量的存储和访问的系统称为其作用域系统,也可以说是存储和访问的规则

常见的编译语言在执行之前经历的三个阶段

  1. 分词/词法分析 代码字符串分离出有意义的词法单元,过程是有状态的则称为词法分析,否则就是简单分词
  2. 语法/语法分析 众多的词法单元组合生成一棵树,抽象语法树(AST)
  3. AST 转换成可执行文件,可以是机器码

js代码执行的过程

编译器读取js代码,识别到声明语句就通知作用域生成相关的变量,同时对于不是声明语句也就是需要执行的动作,编译器生成相关代码交给js执行引擎去执行,引擎执行代码过程中会访问作用域获取需要的变量,也更新一些变量

结论:js代码编译的时刻在执行之前,简单说,首先编译器遍历代码,声明变量,同时生成可执行代码,做好了准备,然后引擎开始执行

执行过程中如何访问变量呢?作用域查询变量的方式

分为LHS和RHS,LHS查询是找到这个变量的目标位置,给其赋值,不关注其原来的值;RHS查询的是变量原来的值,然后可能会使用这个值,而不对变量作处理

作用域嵌套

一段代码块有它的作用域区域范围,如果存在一个代码块在另一个代码块内部呢?这种情况下,作用域被设计成是可嵌套的,内层代码执行时,访问变量,内层找不到就往外层找,一直找到全局作用域,若还不存在,则抛出异常

为什么作用域查找变量需要区分LHS和RHS?

(非严格模式下)当变量没有被声明的情况下,这两种查询或者说引用方式,会导致不同的结果;LHS,作用域会好心自动生成这样的一个变量;RHS,抛出ReferenceError

作用域小结

作用域是一套规则,用于确定在何处以及如何查找变量(标识符)。如果查找的目的是对变量进行赋值,那么就会使用 LHS 查询;如果目的是获取变量的值,就会使用 RHS 查询。 --来自原书《你不知道的JS》

【1-4】闭包的理解

闭包

某个表达式(通常指函数)可以在其词法作用域外执行时访问其词法作用域

形成原因

function A(){
    var a = 1
    function B(){
        console.log(a)
    }
    return B
}
A()()

嵌套函数A包含B,B被通过某种方式(比如值传递)转移到词法作用域A()之外,当函数A执行完成之后,按常理来说当前作用域A应该被释放,但是,因为B使用了A()中的变量a,而且B没有被释放调,B可能会用到变量a,因为变量a有被引用次数,所以a不被释放。

闭包应用

我一直把闭包当作一种特性,当我需要一个封闭的,可长期存在的环境(作用域)的时候,可以考虑构造闭包环境来实现。

let构造闭包环境

for(let i = 0;i < 10; i++) {
    setTimeout(function timer(){
        console.log(i)
    })
}

函数包裹形成闭包环境

for(var i = 0;i < 10; i++) {
    (function(i) {
        setTimeout(function timer(){
            console.log(i)
        })
    })(i)
}

同时可以发现,使用IIFE可以模拟块级作用域哦

【2-2】对象

对象

JS的简单基本类型

string,number,bollean,null,undefined,object

内置(函数)(在object基础上衍生)

  • String, Number, Boolean, Array, Object, Function, Date, RegExp, Error

  • 以上这些不要当作类型看待,当作内置的特殊函数来看待

Object和object的区别,typeof和instance of的区别

  • object是关键字,表示基本数据类型;Object是一个对象(构造函数)(Function类型的),可以被new运算符使用,构造对象实例

  • typeof 和 instanceof 这两个功能就是完全不一样的运算符。typeof 是为了检查数据类型,instanceof是为了看一个变量是否是某个对象的实例。

解释一下为什么有人说js处处皆对象

js当中数据无非就是那么集中,函数,字符串,数值类型,布尔类型

  • 函数,基本所有的函数的构造函数都是Function,至于Function的构造函数是Function,函数既然是构造函数而来,本质上也是对象实例(构造函数是Function)
  • 字符串, js中字符串本来算是基本数据类型,但是js会把字符串默认转换乘String的实例,所以基本你可以看见的字符串本质上也是对象实例(构造函数是String)
  • 数值类型,同字符串一样(构造函数为Number)
  • 布尔类型,同上(构造函数为Boolean)

对象实例的复制

  • 深复制,因为对象本质上是变量(指针)的组织,深复制一般指对象的所有层级的属性和方法都要单独生成(不能引用原来的),深复制有可能碰到循环引用的情况,就比较尴尬
  • 浅复制,最上一层复制,其余引用原来的
  • 深复制JSON.parse(JSON.stringify(obj)) 要求obj必须是JSON安全的

检查属性是否存在

举例,obj.a // undefined, 如何知道对象obj是否定义过属性a(a的值为undefined),还是没有定义过a

  • a in obj 检查属性是否在对象及其原型链中
  • hasOwnProperty 检查对象独有的属性,不检查原型,因为hasOwnProperty是原型函数,如果存在对象没有链接原型(Object.create(null)), obj.hasOwnProperty('a')会报错,所以建议使用Object.prototype.hasOwnProperty.call(obj, 'a')

Node简介

特点

  1. 基于V8引擎
  2. node-webkit项目使得nodejs可以处理UI构建(javascript, html, css),可以用来构建脱离浏览器的桌面应用程序。
  3. -异步I/O, 即读取文件,和ajax请求之类的I/O的操作,进行了异步实现。
  4. 基于事件和回调函数
  5. 单线程
  6. 跨平台 基于libuv 平台架构层

应用场景

I/O 密集型 -- 项目当中处理任务多,输入输出频繁的应用场景。

Cpu 密集型 -- 项目当中任务数量较少,不频繁生成, 但是单个任务的计算量非常大,比如图像处理分析,或者大数据量的筛选处理等。

  1. Node擅长I/O 密集型的应用场景 主要是因为Node相对于其他高级语言来说, Node当中业务逻辑的处理,基本上是基于事件循环和回调函数的,它不会给每个任务
    都分配服务器资源,所以相比较来说,对服务器压力很小。
  2. 那么Node是否不擅长Cpu密集型的场景呢? Node是单线程的, Node单个线程的执行效率(V8引擎)是不弱于其他语言的,和其他语言相比,node的弱势在于它是单线程的
    一个超大的复杂任务如果仅仅给node的主线程来做,那么会Cpu长时间被占用,其他的I/O操作被阻塞, 但是如果可以将大人物拆分成多个小任务,体验将不一样了。CPU密集转换为
    I/O密集

Node解决CPU密集型虽然比较麻烦,但是其中关键在于合理调度服务器资源

【1-3】变量提升和函数提升

变量提升和函数提升

在作用域一节提到过js的执行顺序,先收集声明,做好准备,然后编译代码,再然后执行。也就是说,所有的声明语句无论写在代码的什么位置,在编译执行的时候,都会优先’执行‘,这就是所谓的提升,更精确的说是声明提升

简单说一下

var a = 2 对于这行声明赋值语句,我们必须要有个认识,可以分解成一下:

var a  // 声明语句
a = 2  // 赋值语句

声明语句和赋值语句有个区别,声明语句会进行提升,赋值语句不会

变量提升

代码:

console.log(a) // undefined
var a = 2

实际上:

var a
console.log(a) // undefined
a = 2

代码:

a = 2
var a
console.log(a) // 2

实际上:

var a
a = 2
console.log(a) // 2

函数表达式不提升

代码:

foo() // 2
var foo = function() {console.log(1)}
function foo() {
    console.log(2)
}

实际上:

function foo() {
    console.log(2)
}
foo() // 2
foo = function() {console.log(1)}

变量和函数名同名

函数声明在前,变量声明在后

【1-2】函数作用域和块级作用域

词法作用域

词法阶段的作用域,作用域之间的位置关系由词法阶段代码块的位置来决定

函数作用域 - 遮蔽效应

每一个函数区域会生成一个作用域;遮蔽效应指内外层作用域存在同名变量,内层访问只能访问到内层变量,无法访问到外层变量

注意:可通过window 全局变量来间接访问

关于欺骗词法作用域的方式

  1. eval 动态创建执行代码
  2. with 改变代码块内的作用域环境

这两个机制的副作用是引擎无法在编译时对作用域查找进行优化,因为引擎只能谨慎地认为这样的优化是无效的。使用这其中任何一个机制都将导致代码运行变慢。不要使用它们。 —— 《你不知道的JS》

函数作用域和块级作用域

作用域可以互相嵌套,一层套一层,那么什么情况下会生成一层作用域呢?什么样的结构会生成?

全局作用域

固有的最外层作用域

函数作用域

函数结构会生成作用域,嵌套函数自然就是嵌套作用域

立即执行函数

普通函数的声明执行会导致污染所在的作用域,如果你不想这样可以使用立即执行函数方式

(function foo(){
    var a = 3
    console.log( a )
})()

匿名和具名

在一些需要回调函数的场景中,匿名函数使用的比较多,但是不利于调试,而且想要复用也不太方便(过期的arguements.callee)

setTimeout( function () {
    console.log( "I waited 1 second!" )
}, 1000 )

最好还是养成命名的习惯

setTimeout( function timeLoad() {
    console.log( "I waited 1 second!" )
    // timeLoad()
}, 1000 )

块级作用域

  1. with 创建块级作用域
  2. try/catch
  3. let

let如何生成块级作用域

let是ES6的变量声明方式,只不过和var不同的是,let 声明的变量只存在于当前代码段{...}中,并且不允许重复声明,本质上来说,let就像一个强盗,它劫持了这个代码段这里面的变量声明它说了算,但仅仅在这个代码段有效

if (foo) {
    { // 显式的块
        let bar = foo * 2;
        bar = something( bar );
        console.log( bar );
    }
}
console.log( bar ); // ReferenceError

递归算法**

关于递归

什么是递归

递归是一种用自己定义自己的一种**,比如斐波那契数列,举例来说: 存在f(0) = 1, f(x) = f(x-1) + f(x - 2);

需求

需要得出f(x) x >= 0, 在这非负整数集合内的序列
解决方案:

  1. 迭代循环 - 特点:比较直观的得出答案,效率一般。
  2. 递归求解 - 特点:对于理解算法**有帮助,计算机模拟执行效率较低

结论

递归是一种**,使用它便于理解算法**,也能使得程序代码简洁。但是算法使用必须要有其实用性,在这里递归的方式,对于求解斐波那契数据列效率是非常低下的。
递归应用基本原则:

  1. 基准情形。任何一个可递归解决的问题都必须要有一些基准值的确定,不需要依靠递归。
  2. 不断推进。
  3. 设计法则。 每一步递归推进是可实现可运行的
  4. 合成效益法则。 每一小步算法覆盖率最小。

子序列和问题

  1. 联机算法

O(logN)的一般性判断法则

  1. 能通过O(1)把问题分治为1/2的算法

排序-对分查找

  1. 先排序再查找

欧几德里算法(计算最大公因数)

  1. a, b 均可被z整除 => (ax + by) % z = 0 (x, y j均为整数),此处的z可为所有公因数,包括最大公因数
  2. a % b = c => bx + c = a => a - bx = c 可得知大数除小数的余数 同样也可以被z整除,此处的z可为所有公因数,包括最大公因数
  3. 那么大数和小数的公因数z,同样也是余数c和小数的公因数
  4. 如何得出这个z呢,而且怎么知道它是最大的呢?
  5. 辗转相除法,每次均以小数作为假想最大公因数(很好论证,如果能整除,那么大数和小数的最大公因数就是小数)
  6. 不能整除,说明最大公因数小于小数,而这个时候来看余数c,首先余数能被最那个最大公因数整除,说明余数c 大于 最大公因数,其次 余数 c 小于 小数,此处可将大数和小数的公因数问题转换为小数和余数的最大公因数问题
  7. 再次进行尝试,小数作为假想最大公因数...
  8. 结果最差也就是最后小数一直越来越小,但是不可能为负数,当为0时也是答案出来了,有可能回得出最大公因数为1(这是最差的结果)

取幂算法

  1. f(x) = pow(a, x) 实现函数pow

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.