js学习原理

js 8 种类型

js 作用域提升


持续更新( 有空就更新,没空就不更新了)

JavaScript

是基于对象的语言。

  1. 函数可以像对象一样使用。如作为参数,赋值给变量。作为返回值,等。

  2. 函数闭包

    函数的重要性。了解函数主动维护了在函数内使用的外部的变量,则该函数为一个闭包

  3. 作用域

    不像其它语言,只能依赖函数级别,和全局变量。

  4. 基于原型的面向对象,而不是java 基于类面向对象

对象,原型,函数,闭包 组成了JavaScript

其它的一些功能可以高效写代码

  • 生成器,一次请求生成多次值的函数,不同请求也能挂起执行。
  • Promise,让我们更好的控制 异步代码

ES : ECMScript 语言标准化,目录为止2020年,es6 用得多。

用户还在用旧的浏览器,怎么办? transpilers,转换器+编译器。transformation + compiling

浏览器

  • DOM 文档对象模型

    Web 结构化的UI表现形式。最初是html 。

  • 事件

    事件驱动,定时器,点击,。。。。。

  • 浏览器api

    获取设备信息。。。

实践

  1. 调试

    以前是alert. 现在,firefox 有firebug. chrome 有devtools 。 F12

  2. 测试

    使用断言函数。

  3. 性能分析

    console.time(“name”)
    // 名为name的计时器。
    console.timeEnd(‘name’)
    

    页面构建过程

    1. 生命周期

    2. page 构建阶段

      1. html -> dom。
      2. 执行 js

      会交替执行这两个步骤。

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-765FtiZf-1604636295301)(https://developers.google.com/web/updates/images/2018/07/page-lifecycle-api-state-event-flow.png)]

html -dom 会默认修复一些错误。如 paragraph 放在了head中。

在页面构建阶段,遇到脚本 元素会,暂停html->dom ,转去执行 js.

js 由 js 引擎执行。js 引擎 各个浏览器不尽相同。chrome 是v8

浏览器提供一些全局对象,如window 对象,有一个属性document

事件处理

生命周期第二部分:事件处理

单线程模型??

所有已经生成的事件(无论是用户的还是服务器的ajax等)都在同一个事件队列中。按被检测到的顺序执行。

事件是异步的。

对事件的处理,以及处理函数的调用是异步的。

注册事件处理器
  • 赋值某个特殊属性
  • 内置addEventListener方法。

函数

概念:函数是第一类对象

注意js 不是函数式编程!

ES6 ,增加 剩余参数,与默认参数

  • 回调函数在哪种情况 下会同步,或者异步
  • 箭头函数和函数表达式的区别是什么
  • 你为什么要在函数在使用默认 参数。

全局js 代码是在页面构建阶段执行的。其它的大多是函数。

函数式不同点是什么

函数是第一类对象
  • 字面量创建
  • 赋值给蛮,数组 或者其它属性
  • 作为函数的参数传递
  • 作为函数返回值
  • 具有动态分配和创建的属性
函数式编程
  • 把函数作为第一类对象是函数式编程(functional programming)的第一步
回调函数
function useless(ninjacallback){
    return niniacallback();
}
//这函数没有什么用
// 但反映了函数的一种能力,即函数作为另一个函数的参数,随后通过参数来调用该函数

js 可以在表达式出现的任意位置创建函数。

使用比较器 进行排序,数组都能sort ,可以传函数进去回调,返回一个+ - 0 三个 来调换位置,只是比较两个值时,进行回调我们的函数。

函数作为对象的乐趣

你可以给函数添加属性

var ninja={};
ninja.name="hi";//新对象加属性
var wieldsword= function(){};
wieldsword.sw='kata';//函数分配一个属性

//两种非常相似

比如,某些算法,可以保存返回值,提高性能。

存储函数

回调函数集合,怎么判断 里面的函数同与不同。

如一个集合,判断这个函数是重复的吗?

循环判断集合中是否已有,显然这样性能很差。

可以加上属性id 来判断 。如果,已经有这个属性id ,则说明已经被加入过了。就是重复了。没有的话,加上属性。

自记忆函数

能够记住上次计算结果 。,结果按参数存储,别人调用取出参数。

函数定义

js 中通过函数字面量 functional literal 来创建函数值。

  • 函数定义 和函数表达式

    function declarations function expressions

  • 箭头函数,也叫lambda函数

    ES6的特性

    myArg=>myArg*2

  • 函数构造函数

    这人不怎么用。以字符串的形式构造一个函数

    new Function('a','b','return a+b');
    
  • 生成器函数

    ES6中新增的功能。

    不同于普通函数。这种函数能够退出再重新进入 ,再进入之间保留函数内变量的值。

    function* myGen(){yied 1;};
    
    函数声明和函数表达式

    这是最原始的定义函数。

    函数声明:

    function name(arg){};

    函数表达式:

    var a=function(){};//作为赋值表达式的右值
    myFunction(function(){});// 作为其他函数的参数。
    

    函数声明来说,函数名强制的。函数表达式来说,函数名则是可选的。

    立即函数

    标准化调用:myFun(3);

    立即调用: (function(){})(3);

    为什么要加() 因为解析器要区分函数声明还是函数表达式。

    箭头函数

    param => expression

    (()=> a-b )

    只有一个参数的庆,括号可以省。没有参数反而不能省。

    没有返回值,则默认是undefined

    形参和 实参

    argument parameter

剩余参数

ES6

function multiMax(first,...remainingNumbers){
    //其实对象?
}
默认参数
function performAction(action="defalut"){}
//以前是三目运算符来做。现在简单

函数调用

为什么this表示函数上下文

function 和method 之间区别

隐式函数传递,默认传递 this 和 arguments这两个参数。

arguments参数

是传递给函数的所有参数的集合

它不是数组。一种类数组结构。

传过去的可以多于。

this参数,函数上下文

当调用函数时,除了显式提供的参数外,this参数也会默认传递。

this 指的是什么,严重受到函数调用方式影响。不仅仅是定义函数的方式和位置决定。

函数调用
  • 作为一个函数function skulk() 。直接调用
  • 作为一个方法 method ninja.skulk()。关联在一个对象上,实现面向对象
  • 作 一个构造函数 constructor new Ninja() . 实例化一个新的对象
  • 通过函数的apply 或者call方法 - skuli,apply(ninja) skulk,call(ninja)
  1. 作为函数调用

    有两种可能 上下文为this 或者 undefined

  2. 作为方法调用

    this 可能为

  3. 作 一个构造函数

    没有什么特别的。

  4. apply call

    你可能注意到,上面的方法主要区别是:最终作为函数上下文传递给执行函数的对象的不同。比如,对于方法而言是方法所在的对象。对于 顶级函数而言是window。构造函数是新创建对象的实例。等等。

    但如果想改变上下文怎么办?好吧自己实现可能会有一些问题。

    所以,使用js提供的 apply call 来。。。apply传递两个参数一个是上下文对象 和一个数组作为函数调用的参数。

解决上下文问题

前面说了可以用apply 和call 来处理。

我们还可以用箭头函数绕过函数上下文。

以及bind方法

箭头函数绕过函数上下文

箭头函数作回调函数有一个特征:箭头函数没有单独的this值。this与所在的上下文相同。

bind方法

闭包和作用域

一个变量或方法有几种不同的作用域?这些作用域分别 是什么

如何定位 标识 符及其值

什么是可变变量?

理解闭包

闭包允许函数访问并操作逊外部的变量。只要变量或函数存在于声明函数时的作用域内,闭包即可使用函数能够访问这此变量或函数。

var outervalue="aa";
function outerfun(){
    assert(outervalue==="aa");
}
//变量和函数 都是在全局中声明的,这一个作用域(实际就是闭包)从未消失。
var outerValue="外部";
var later; //声明一个空变量,稍后使用

function outerFunction(){
    var innerValue ='ninja';

    function innerFun(){ //内部函数,声明这个函数时,innerValue是在内部函数作用域的
        assert(outerValue==="外部","外部");
        assert(innerValue==='ninja','ninja')
    }
    later = innerFun; //  later是全局的,所以,调用并存储引用
}
outerFunction();
later();//调用内部函数

内部作用域消失后还能访问innerValue ?

你确定不是因为 用的是var 而不是let??

只要内部函数一直存在,内部函数的闭包就一直保护该函数的作用域中的变量。

image-20201106105304530

使用闭包

封装私有变量

原生的不支持私有变量。

es6 都有let了,

怎么感觉面向对象了。

回调函数是另外一种常见使用闭包的场景

通过执行上下文来跟踪代码

​ 在 JavaScript中,代码执行的基础单元是函数。我们时刻使用函数,使用函数进行计算,使用函数更新UI,使用函数达到复用代码的目的,使用函数让我们的代码更易于理解。为了达到这个目标,第一个函数可以调用第二个函数,第二个函数可以调用第三个函数,以此类推。当发生函数调用时,程序会回到函数调用的位置。你想知道 JavaScript引擎是如何跟踪函数的执行并回到函数的位置的呢?
​ JavaScript代码有两种类型:一种是全局代码,在所有函数外部定义;一种是函数代码,位于函数内部。 JavaScript引擎执行代码时,每一条语句既然具有两种类型的代码,那么就有两种执行上下文:全局执行上下文和函数执行都处于特定的执行上下文中。

两种上下文。二者最重要的差别是:全局执行上下文只有一个,当 JavaScript程序开始执行时就已经创建了全局上下文;而函数执行上下文是在每次调用函数时,就会创建一个新的。

注意: 了当调用函数时可通过关键字访问函数上下文。函数执行上下文,虽然也称为上下文,但完全是不一样的概念。执行上下文是内部的 JavaScript概念, JavaScript引擎使用执行上下文来跟踪函数的执行。
JavaScript基于单线程的执行模型:在某个特定的时刻只能执行特定的代码。一旦发生函数调用,当前的执行上下必须停止执行,并创建新的函数执行上下文来执行函数。当函数执行完成后,将函数执行上下文销毁,并重新回到发生调用时的执行上下文中。所以需要跟踪执行上下文—正在执行的上下文以及正在等待的上下文。最简单的跟踪方法是使用执行上下文栈(或称为调用栈)

js 变量类型

你可以 var let const 来定义变量

  1. const

    不可再赋值,但可修改已存在的值。

  2. var

    该变量是在距离最近的函数内部或是在全局词法环境中定义。(忽略块级作用域)。

    全局环境,块级环境,函数环境。

  3. let

    与var不同,let 直接在最近的词法环境中定义变量。

生成器与promise

generator and promise

生成器的主要用途是什么

js 的单线程模型,是怎么的??

promise

.then

.err

  1. 拒绝promise

  2. 链式调用promise

    then then.then.then .err

  3. 等待多个promise

    除了处理相互依赖的异步任务序列以外,对于等待多个独立的异步任务,

async函数

前面的还书写一些样板代码,所以 需要一个async来管理所有promise的函数调用。

面向对象与原型

可以在原型上增加特定属性。

原型虽然类似于class,但又不完全是。

在js 中可以通过原型实现继承。

每个对象都有原型的引用,当查找属性时,若对象本身不具有该属性,则会查找 原型上是否有该属性。

对象构造与原型

var a={}

function ninja(){};

ninja.prototype.swing=function(){return true;} // 对原型修改。

动态特性的副作用

容易的修改属性导致了。。。

构造函数实现对象原型
实现继承

复制原型

instanceof 操作符

java中instanceof检测左边的类与右边的为是否是同一个子类。

js 中也差不多,只是使用在原型链中。

使用es6中js 的class

前面的继承太麻烦了。

对于java转js的人来说不友好 。

所以模拟了class ,也就是语法糖。

实际上底层还是原型继承。

静态方法

static

继承

extends

es6之前实现继承是一件痛苦的事。

控制对象的访问

理解getter 和setter

js是容易修改属性的

代理:通过代理来控制访问。es6引入的。

getter setter

//之前方法
function jj(){
    let a=‘s’;

this.geta()=()=> a;
}
//定义get set 
// 在对象字面量定义,或者在es6的class中定义
//在内置的Object.defineProperty定义。

使用代理来访问

Proxy

new Proxy

可以使用代理来记录日志。检测性能,自动填充属性。实现负数组索引。等等的用法。

问题: 性能上会有损耗。

处理集合

map 与set

数组

Map

对象不等于MAP!!

Set

集合的元素是唯一的。可以了解是怎么唯一的

es6之前只能模拟,。现在可以直接用。

并集
交集
差集

正则表达式

非常有用。

术语与操作符

精确匹配

转义

起止符号

重复出现

分组

预定义字符集

精确匹配

或操作符

反向引用

编译正则表达式

捕获匹配的片段

简单
全局表达式匹配
捕获的引用
未捕获的分组

利用函数进行替换

string.replace

代码模块化

js 到处都是全局变量

复杂度,。作用域

es6之后就提供了很好的特性

之前 是使用对象,闭包和立即函数来实现模块。

ES6模块

结合之前 的commonjs(语法简单优点)与amd(异步优点)的优点

export 与import

导入与导出功能。

默认导出

Dom操作

避免布局抖动

修改布局

React 的虚拟Dom 。 对虚拟dom修改而不考虑布局抖动。恰当的时候react会判断实际的dom要怎么改。 这种创新的批处理方式,提高了性能

历久弥新的事件

事件循环

计时器

settimeout setinterval

处理事件

dom代理事件:捕获与冒泡

自定义事件

跨浏览器开发的技巧

对es的支持

选定一种主发开发。

api

测试套件

es6的附加特性

模板字符串

字符串加变量一起定。加反引号

解构

就是从对象 数组中提取数据作为变量?

增强版的对象字面量

测试与调试技巧

fiddler

firefox的firebug

f12

测试用例???

测试框架的基本原理

断言
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值