JS 基础快速入门

JS 基础快速入门

JS 基础知识点

变量类型和计算

值类型

boolean number string 使用 typeof 可以很容易的区分出来

引用类型

object Array Function 变量只是对象的一个指针
引用类型可以无限添加属性,不论是对象还是数组还是方法都可以任意添加属性
引用类型可以避免占用过大的内存

变量计算(强制类型转换)

var a = 100 + '1' // '1001'
100 == '100' //true
0 == '' //true
null == undefined //true  false == false
if (''){} //false 同样的还有 0 NaN 
console.log(!window.abc) // true

判断一个变量会被当做 true 还是 false

console.log(!!a)

=== 和 ==

全部用 ===
除了以下这种情况,判断为空

if (obj.a == null)
{
    //这里相当于 obj.a === null || obj.a === undefined
}

JSON

json 是一种内置的数据对象,也是一种数据结构

原型链

构造函数

基本上大写开头,

function Foo(name,age)
{
    this.name = name
    this.age = age
    this.class = 'class-1'
}
var f = new Foo('zhangsan',32)

var a = {} //推荐
var a = new Object()
var a = [] //推荐
var a = new Array()
function Foo(){} //推荐
var Foo = new Function(){}

使用 instanceof 来判断一个函数是否是一个变量的构造函数

原型规则

  • 引用类型都可以自由扩展属性
  • 所有引用类型都有一个__proto__属性,称为 显示原型,指向构造函数,比如: obj.__proto__ === Object.prototype
  • 如果一个对象没有某个变量,那么会去它的显示原型也就是 proto 里面去寻找,因为 proto也可以被扩展的。

这样处理会带来一个问题,就是在for in语法中会打印出它所有的属性,虽然在高级浏览器中已经屏蔽了来自原型的属性,但是还是建议添加

for (item in f)
{
    if (f.hasOwnProperty(item))
    {}//加个判断
}

补充,这里 Object,Array实际上是一个构造函数

原型链

f.toString()

为什么这个方法能执行成功,f 并没有toString方法,于是但 f.__proto__里面查找,也没有。这时候会去查找显示原型的原型,f.__proto__.__proto__ 也就是 Object 构造函数,发现有 toString 属性,于是执行方法。

这里可以看出 instanceOf 的逻辑,也就是一层层向上查找

作用域

执行一个未声明的函数不会报错,所有的变量和函数都会初始化为 undefined。如果后面有声明或者是实现,那么会被自动提前。也就是说一旦声明了函数,就可以在任何地方执行。
执行上下文 也就是在执行之前会把作用域内所有的函数声明收集起来。
注意函数声明和函数表达式的区别

this

this 只有在执行时候确认,定义时候无法确认。

  • 作为构造函数执行
  • 作为对象属性执行
  • 作为普通函数执行
  • call apply bind
function Foo(name){
    this.name = name
}//作为构造函数执行

var obj = {
    name:'A',
    printA:function(){
        console.log(this.name)//作为对象属性执行
    }
}

//使用call改变 this 的值
function fn(name,age){
    console.log(this) // this == window
}     
fn.call({x:100},'zhangsan',20)
//this == {x:100}

js没有块级作用域,也就是说和一般的 java、C# 不一样,有函数作用域和全局作用域。
全局作用域定义在根部,任何人都可以修改和访问。
函数作用域,变量声明在函数体里面,有点类似命名空间

作用域链

类似响应链的概念,如果本级作用域没有找到这个变量,那么到上级作用域里面查找,直到全局作用域.

闭包

  • 函数作为返回值
  • 函数作为参数传递

闭包实际应用中主要用于封装变量,收敛权限

var i
for (i = 0;i<10;i++)
{
    (function(i){
     var a = document.createElement('a')   
     a.innerHTML = i + '<br>'
     a.addEventListener('click',function(e){
            e.preventDefault()
            alert(i)         //如果不使用闭包的话,这里的 i 会变成自由变量,那么真正点击的时候会是什么值就不一定了
         })
    })(i)
}

异步

在可能发生等待的时候

  • setTimeout setInterval
  • ajax 请求
  • 图片加载

浏览器渲染过程

DOM

  • attribute 指的是 HTML tag 上的属性 比如 src -setAttribute
  • property 指的是 DOM 节点的属性,比如 children

JS 开发环境

模块化

如果代码都是全局的,那么会污染全局变量;
模块化:如果用哪个就使用哪个

require.js

全局 define 函数,全局 require 函数,依赖 JS 会自动加载;只有 define 过后才能 require
也就是说,引用 require 之后,全局属性会有一个 define 函数和 require 函数。
根据依赖关系,自动异步加载

//utils.js
define(function(){
    var util = {}
    return util    
    })
//a-utils.js
define(['./utils.js'],function(util){ //这里的 util 表示 utils.js 的返回值
    var a-utils = {
        utils.functionXX()
    }
    return a-utils
}
//main.js
require(['./a-utils.js'].function(a){
  operation()  
})

Common.js

nodejs 规范,不会异步加载,而是同步加载(因为是服务端)

//utils.js
module.exports = {
    functionXXX:function(){}
}

//a-utils.js
var util = require('utils.js')
module.exports = {
    functionYYY:function(){
        util.functionXXX()
    }
}

打包webpack

大坑,待填

压缩

## JS API

内置函数

  • Object

Array

-forEach
-every 判断所有元素符合条件
-some 判断至少有一个元素符合条件

  • Boolean
  • Number
  • String
  • Function

Date

-now
-getTime
-getMonth
-getHours

Math

-random 随时改变,清除缓存

var random = Math.random()
var random = random + '0000000000'
var random = random.slice(0,10)// 避免报错
console.log(random)
  • RegExp
  • Error

事件绑定

原本的绑定是基于addEventListener的,比如

function bindEvent(elem,type,fn)
{
    elem.addEvnetListener(type,fn)
}

对于同类的事件处理,一般的处理方式是在父节点绑定事件,因为事件冒泡的原理。比较容易处理。注意这时候需要 stopPropatation

事件代理
div1.addEventListener('click',function(e){
        var target = e.target //e.target 就是发出事件的元素,使用代理可以让代码更简洁;
        if (target.nodeName === 'xx') //限定 node 节点
        {
            //dosth
        }    
    })

浏览器渲染页面过程

  1. 根据 HTML 结构形成 DOM 树
  2. 根据 CSS 生成 CSSOM,也就是说应该尽早形成 CSSOM
  3. 将 DOM 和 CSSOM 整合为 RenderTree
  4. 根据 RenderTree 开始渲染和展示
  5. 遇到<script>标签会执行并且 阻塞 渲染,也就是说,尽可能让页面结构 HTML,先形成 DOM 树,再执行 script

window.onload 与 DOMContentLoaded

window.addEventListener('load',function(){})//页面资源全部加载好之后才会执行
document.addEventListener('DOMContentLoaded',function(){})//DOM  渲染好就执行,此时图片和视频可能没有加载完

资源优化

  • 静态资源合并优化和缓存(比如脚本后面加版本号,如果版本号一致就不再请求,如果内容一致应该不需要改变版本号)
  • CDN 加速
  • 服务端渲染
  • 懒加载
  • DOM 操作和查询,比如getElementsByTagName 这样的操作
  • 合并 DOM 操作,比如将结果先写成一个片段,然后再加入到 DOM 里面document.createDocumentFragment

AJAX

手动编写一个 AJAX(XMLHttpRequest)

var xhr = new XMLHttpRequest()
xhr.open("GET","/api",false)
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4)//任务完成,0 未初始化,1 正在发送请求,2 send 方法完成,接收到全部响应内容,3 住在
    {
        if (xhr.status == 200)//服务端返回状态码,2xx请求成功,3xx需要重定向,4xx 客户端请求错误,5xx服务端错误
        {
            alert(xhr.responseText)
        }
    }
}

跨域

浏览器有同源策略,不允许 ajax 访问其他接口,协议(http)、域名、端口,有一个不同就算跨域。
允许跨域的标签:

  • img 比如用于打点统计
  • link 可以使用 cdn
  • script 可以使用 JSONP

存储

  • cookie 客户端和服务端通信,只不过本身带有存储数据的能力,存储量较小,
  • locationStorage 存储量为5M,-localStorage.setItem 不会被主动清除 (safari 的隐藏模式下,使用 getItem 会报错,需要用 trycatch)

上线和回滚

上线流程

  1. 提交测试代码到 master 分支
  2. 将当前服务器代码打包加 tag,备份
  3. 将 master 分支代码提交到服务器,生成新的版本号

回滚流程

  1. 将当前服务器代码打包加 tag,备份
  2. 将备份的解压,覆盖服务器,生成版本号

Linux 部分命令

  • head [filename]
  • tail [filename]
  • ll
Comments
Write a Comment