【个人笔记】前端开发笔记整理

JavaScript

(参考了《JavaScript高级程序设计》和部分知乎答案)


作用域

指可访问变量对象函数的集合。

局部作用域:在函数内声明,只能在函数内部访问
全局作用域:在函数外定义,所有脚本和函数均可使用(函数内赋值但未声明,仍为全局变量
变量生命周期:全局变量在页面关闭后销毁,局部变量在函数执行完毕后销毁

ps:在HTML中所有数据属于window对象


数据类型

原始数据类型:栈,占据空间小,大小固定
String
Number
Boolean
Object
Function


不含值的数据类型:
Undefined:不存在的值,或变量被声明了但未赋值
Null:一个对象被定义了,但是为空值(没有任何属性和方法)


引用对象类型:堆,占据空间大,大小不固定(在栈中储存了指针,指向堆中的起始位置)
Object
Date
Array


boolean类型转换
数据类型 true false
Boolean true false
String 任何非字符串 ""(空)
Number 任何非零数字值 0和NaN
Object 任何对象 Null
Undefined n/a(不适用) underfined

例子:

var message = "Hello world!";
if (message) {
  alert("Value is true");
}

正则表达式

由一个字符串序列形成的搜索模式。
如:

var str = "Visit W3cSchool!";
var n = str.search(/W3cSchool/i);
//n=6               (不区分大小写)

变量提升

函数声明和变量声明会被解释器自动提升到方法体的最顶部

var x;

但是初始化的变量不会提升

var x = 5;
x = 5

为避免问题的出现,通常在作用域开始前声明变量

注意:函数声明也会自动提升,而传递给初始化变量的函数则不会

function fn () {} //提升

var fn = function () {} //不提升

函数调用的四种方法

1.方法调用模式

var myobject = {
  value: 0,
  inc: function() {
    alert(this.value);
  }
}
myobject.inc();

//this指向myobject

2.函数调用模式

var add = function(a,b) {
  alert(this);
  return a+b;
}
var sum = add(3,4);
arert sum;

3.构造器调用模式(摒弃)

4.apply调用

var arr = [10,20];
var sum = add.apply(myobject,arr);
aleat(sum);

原型链

当从一个对象那里读取属性或调用方法时,如果该对象不存在这样的属性或方法,就会去自己关联的prototype对象那里寻找,直到找到或追溯过程结束为止。(即对象的属性和方法追溯机制)

”读“属性会沿着原型链搜索,”新增“属性时则不会去看原型链

(obj)
name:'obj'        valueOf
__proto__  ——>    toString
                  constructor
                  ...
                  __proto__    ——>    null

闭包

先看两个典型例子

function foo () {
  var local = 1;
  function bar () {
    local++;
    return local;
  }
 return bar;
}

var func = foo();
func(); //2
func(); //3

bar函数调用了外层函数的local变量,函数运行完毕后local仍然保存在内存中,所以每次运行函数后local都会增加1

var add =(function () {
  var counter = 0;
  return function () {
    return counter += 1;
  }
})();

add(); //1
add(); //2
add(); //3

和上一个例子的原理是一样的,内层函数调用了外层函数的全局变量count导致其始终存在于内存中,而内部函数的存在也依赖于外层函数,导致其也始终再内存中,不会在调用结束后被垃圾回收机制回收。

这就叫闭包,一句话概括:闭包就是函数函数内部能访问到的变量的总和。
或者说,如果存在有权访问另一个函数作用域中变量的函数,那就构成了闭包。

它提供了一中间接的方式能够访问到函数内部的数据,有以下两种情况:
1.函数作为返回值
2.函数作为参数传递

正确运用闭包由一个好处,就是让一些数据更安全,只能通过特定的接口来访问。

当然,有时候闭包也会导致一些问题,如下面的例子:

for (var i=0; i<10; i++) {
  arr[i] = function() {
    return i;
  }
}

arr[0]; //10
arr[6]; //10

function内访问了外部变量i,构成了一个闭包,我们先不写内部的i,每次赋值的结果如下

arr[0] = function() { return i };
arr[1] = function() { return i };
...
arr[10] = function() { return i };

而i的作用域是整个for的花括号内,因此这些函数返回的是同一个i,遍历完后产生了这11个结果,此时我们再调用函数的时候,i已经为10了,因此无论调用哪个函数,结果都是遍历完后的i。


this
var obj = {
  foo: function () {
    console.log(this);
  }
}
var bar = obj.foo;

obj.foo(); //obj
bar(); //window

要理解this,首先要知道函数的三种调用形式

func(p1,p2);
obj.child.method(p1,p2);
func.call(context,p1,p2); //正常形式

context就是this,
上面的例子中,bar()等价于func.call(undefined),这种情况下this为window,
而obj.foo()等价于obj.foo.call(obj),this为obj

有一个特例:

function fn() {
  console.log(this);
}
var arr = [fn,fn2];

arr[0]; //这里的this指什么

我们把arr[0]假想为arr.0()
也就相当于arr.0.call(arr)
所以this为arr

对某些框架有其他方法来理解,
如在jQuery,this关键字指向的是当前正在执行事件的元素。


new操作

1.创建一个空对象,并且this变量引用该对象,继承该对象的原型

var obj = {}

2.属性和方法被加入到this引用的对象中

obj.__proto__ = Base.prototype;

3.新创建的对象又this所引用,并且隐式地返回this

Base.call(obj);

在以下例子中

var o = new myObject();

一旦没有加上new,myObject()内部的this将指向全局对象


事件类型
UI事件

1.load事件:页面完全加载后触发

2.unload事件:页面完全卸载后触发

3.resize事件:当浏览器窗口被调整到一个新的高度或宽度时触发

4.scroll事件:文档被滚动期间触发

焦点事件

1.focusout:在失去焦点的元素上触发

2.focusin:在获得焦点的元素上触发

3.blur:在失去焦点的元素上触发

4.DOMFocusOut:在失去焦点的元素上触发

5.focus:在获得焦点的元素上触发

6.DOMFocusIn:在获得焦点的元素上触发

鼠标与滚轮事件

1.click:单击鼠标或按下回车键时触发

2.dbclick:双击鼠标按钮时触发

3.mousedown:按下任意鼠标按钮时触发

4.mouseup:用户释放鼠标按钮时触发

5.mousewheel:通过鼠标滚轮滚动页面时触发

6.mouseenter:鼠标光标首次从元素外部移动到元素范围内时触发(只限于被选元素)

7.mouseover:鼠标指针位于一个元素外部,用户将其首次移入另一个元素边界之内时触发(任何元素,不限于被选元素)

8.mouseleave:位于元素上方的鼠标光标移动到元素范围之外时触发(只限于被选元素)

9.mouseout:鼠标指针位于一个元素的上方,移入到另一个元素时触发(任何元素,不限于被选元素)

10.mousemove:鼠标指针在元素内部移动时重复地触发

键盘与文本事件

1.keydown:按下键盘的任意键时触发

2.keypress:按下键盘的字符键时触发

3.keyup:释放键盘上的键时触发

除此之外,还有

变动事件
H5事件
触摸与手势事件

DOM事件处理程序
DOM0级事件处理程序
var btn = document.getElementById("myBtn");

btn.onclick = function () {
  alert("clicked");
}
DOM2级事件处理程序
var btn = document.getElementById("myBtn");

btn,addElementListener("click",function(){
  alert("clicked");
},false);

//true: 在捕获阶段调用事件处理程序
//false: 在冒泡阶段调用事件处理程序
跨浏览器的事件处理程序(封装)
var EventUtil = {
  addHandler: function(element,type,hander) {
    if (element.addEventListener) {
      element.addEventListener(type,handler,false);
    } else if (element.attachEvent) {   //IE
      element.attachEvent("on"+type,handler);
    } else {
      element["on"+type] = handler;   //HTML事件
    }
  }
}

事件委托的原理以及优缺点
function delegateEvent (interfaceEle,selector,type,fn) {
  if (interfaceEle.addEventListener) {
    interfaceEle.addEventListener(type,eventfn);
  } else {   //IE
    interfaceEle.attachEvent("on"+type,eventfn);
  }
  function eventfn (e) {
    var e = e || window.event;
    var target = e.target || e.srcElement;   //兼容fireFox
    if (matchSelector(target,selector)) {
      if (fn) {
        fn,call(target,e);   //将fn内部的this指向target
      }
    }
  }
}

var odiv = document.getElementById("iDiv");
delegateEvent(odiv,'click',function(){
  alert("clicked");
});

优点:
1.大量减少内存占用,减少事件注册
2.新增子对象无需再次对其绑定事件


原生Javascript实现事件代理
  • 1
  • 2

这段代码监听了整个

    标签并且启用了事件代理,点击
  • 标签的时候会返回具体的li标签的id,对新增的对象元素也同样有效


    事件冒泡和事件捕获

    事件冒泡:事件开始时由最具体的元素接收,然后逐级向上,传播到较为不具体的节点

    事件捕获:不太具体的节点更早地接收到事件,而最具体的节点最后接收到事件

    DOM事件流:同时支持两种事件模型:捕获型事件和冒泡型事件,但是,捕获型事件先发生。两种事件流会触及DOM中的所有对象,从document对象开始,也在document对象结束。

    支持W3C标准的浏览器在添加事件时用addEventListener(event,fn,useCapture)方法,基中第3个参数useCapture是一个Boolean值,用来设置事件是在事件捕获时执行,还是事件冒泡时执行。而不兼容W3C的浏览器(IE)用attachEvent()方法,此方法没有相关设置,不过IE的事件模型默认是在事件冒泡时执行的,也就是在useCapture等于false的时候执行,所以把在处理事件时把useCapture设置为false是比较安全,也实现兼容浏览器的效果。


    JSON

    json的全称为JavaScript Object Notation,即对象表示法,是一种约定的数据格式。


    AJAX

    ajax的全称为Asynchronous JavaScript and XML,即异步的JavaScript和XML,
    理解它的过程很简单,就是用JS发起一个请求,并得到服务器返回的内容,原生JS写法如下:

    //第1步 声明一个对象
    var request; 
    //第2步 根据浏览器赋予对象http请求的方法
    if (window.XMLHttpRequest) { //code for IE7+, Firefox, Chrome, Opera, Safari
      request = new XMLHttpRequest();
    } else { //code for IE6, IE5
      request = new ActiveXObject("Microsoft.XMLHTTP");
    }
    //第3步 确定服务器返回的方法
    request.onreadystatechange = function () {
      if (this.readyState == 4 && this.status == 200) {
        console.log(request.responseText);
      }
    }
    //第4步 在之前声明的基础上发起请求
    request.open("GET","filename",true);
    request.send();
    

    注意以下要点:

    IE6及以下版本用的是ActiveXObject方法,其余用XMLHttpRequest方法。

    XMLHttpRequest对象三个重要的属性:

    onreadystagechange 存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。

    readyState 存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
    0: 请求未初始化
    1: 服务器连接已建立
    2: 请求已接收
    3: 请求处理中
    4: 请求已完成,且响应已就绪

    status
    200:"ok"
    404:未找到页面

    XMLHttpRequest对象的open()和send()方法:

    open(method,url,async);
    //规定请求的类型、URL 以及是否异步处理请求。
    //method:请求的类型;GET 或 POST
    //url:文件在服务器上的位置
    //async:true(异步)或 false(同步)
    
    send(string);   
    //将请求发送到服务器。
    //string:仅用于 POST 请求
    

    与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。
    然而,在以下情况中,请使用 POST 请求:
    1.无法使用缓存文件(更新服务器上的文件或数据库)
    2.向服务器发送大量数据(POST 没有数据量限制)
    3.发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠

    jQuery封装了AJAX的方法,只需要一行代码:

    $.get('filename').then(function(response){
      //do something
    });
    

    原型继承与扩展
    Child.prototype = new Parent();
    

    把父类对象赋值给子类构造函数的原型,这样子类就可以访问到父类以及父类的原型,这就叫原型继承

    function Person(name) {
      this.name = name;
    }
    
    Person.prototype.sayHello = function() {
      alert ("hello, I'm" + this.name);
    };
    
    var BillGates = new Person("Bill Gates"); //建立对象
    BillGates.sayHello(); //hello, I'm Bill Gates
    
    Person.prototype.Retire = function() {
      alert("poor"+this.name+"byebye!");
    } //建立对象后再动态扩展
    
    BillGates.Retire(); //poor BillGates byebye!
    

    这种建立对象后再动态扩展的情况,就叫做原型扩展,新方法仍然可被之前建立的对象调用


    js延迟加载

    defer和async是动态创建dom的两种方式,defer是延迟加载,async是异步下载脚本
    在其他情况下,浏览器会按照script元素在页面中出现的顺序依次进行解析


    封装与模块化开发

    使代码规范好用,使用简单化,只需要知道参数和返回值,可以转化编程思维角度

    var modulel = (function(){
      var _count = 0;
      var m1 = function(){
      //...
      }
      var m2 = function(){
      //...
      }
      return {
        m1:m1,
        m2:m2
      };
    })();
    

    跨域问题的解决方法

    1.jsonp(jQuery的$.getScript方法就是利用jsonp跨域解决的)
    2.iframe
    3.window.name
    4.window.postMessage
    5.服务器上设置代理页面


    DOM操作

    (1)创建新节点

    createDocumentFragment() //创建一个DOM片段
    createElement() //创建一个具体元素
    createTextNode() //创建一个文本节点
    

    (2)添加、移除、替换、插入

    appendChild()
    removeChild()
    replaceChild()
    insertBefore() //在已有子节点前插入新的节点
    

    (3)查找

    getElementsByTagName() //通过标签名称
    getElementsByName() //通过元素Name属性值
    getElementById() //通过元素id,唯一,所以Element没有s
    

    前端模块化开发
    发展历程

    1.函数封装

    function f1 () {
      statement
    }
    function f2 () {
      statement
    }
    

    污染了全局变量,容易发生冲突,且模块成员之间没有联系


    2.对象的写法

    var myModule = {
      var1: 1,
      var2: 2,
      fn1: function () { },
      fn2: function () { }
    }
    

    调用myModule.fn2(); 避免了变量污染,只需要保证模块名唯一即可
    缺陷是外部可以随意修改内部成员:

    myModule.var1 = 100;
    



    3.立即执行函数的写法

    var myModule = (function(){
      var var1 = 1;
      var var2 = 2;
      function fn1 () { };
      function fn2 () { };
      return {
        fn1: fn1,
        fn2: fn2
      };
    }) ();
    
    console.info(myModule.var1); //underfined
    

    这样就无法修改暴露出来的变量和函数,就是模块化的基础。

    模块化的规范 CMD和AMD

    commonJS 通用模块定义
    1.定义模块
    每一个模块都是一个单独的作用域,无法被其他模块读取
    2.模块输出
    模块只有一个出口,module.exports对象,把模块希望输出的全部内容放入该对象
    3.加载模块
    加载模块使用require方法,该方法读取一个文件并执行返回文件内部的module.exports对象

    例子

    //模块定义myModel.js
    var name = 'Byron';
    function printName () {
      console.log(name);
    }
    function printFullName(firstName) {
      console.log(firstName + name);
    }
    module.exports = {
      printName: printName,
      printFullName: printFullName
    }
    
    //加载模块
    var nameModule = require(./myModel.js);
    nameModule.printName
    

    AMD 异步模块定义


    综合知识

    关于缓存的三个关键字

    cookie:是储存在浏览器上的一小段数据,用来记录某些当页面关闭或刷新后仍然需要记录的信息。
    session:是一种让服务器能够识别某个用户的机制。
    localStorage:HTML5本地储存web storage特性的API之一,用于将大量数据保存在浏览器中。


    前端性能优化

    1.减少http请求次数,JS、CSS源码压缩
    2.前端模版,JS+数据,减少DOM操作次数,优化js性能
    3.用innerHTML代替DOM操作,减少DOM操作次数,优化js性能
    4.设置className,少用内联style
    5.少用全局变量,缓存DOM节点查找的结果
    6.图片压缩和预加载,将样式表放在顶部,脚本放在底部,加上时间戳
    7.避免使用table,显示比div+css布局慢


    页面加载过程

    1.浏览器根据请求的URL交给DNS域名解析,找到真实IP,向服务器发起请求
    2.服务器交给后台处理完成后返回数据,浏览器接收文件(HTML、JS、CSS、图片等)
    3.浏览器对加载的资源进行语法解析,建立相应的内部数据结构
    4.载入解析到的资源文件,渲染页面,完成


    浏览器渲染过程

    1.浏览器解析html源码,然后创建一个DOM树,每一个标签都有一个对应的节点,并且每一个文本也有一个对应的文本节点(DOM树的根节点就是documentElement,对应html标签)
    2.浏览器解析CSS代码,计算最终的样式数据(对CSS中非法的语法会忽略掉,按优先级排列:浏览器默认设置>用户设置>内联样式>外链样式>html中的style)
    3.构建渲染树(忽略不需要渲染的元素)
    4.根据渲染树把页面绘制到屏幕上


    XHTML

    可拓展超文本标记语言,将HTML作为XML的应用而重新定义的标准
    其中script需要写成以下形式才能被识别

    
    

    CSS

    css定义的权重

    div:1
    .class:10
    #id:100
    内联样式表:1000
    #id div:100+1=101
    .class div:10+1=11
    .class1 .class2 div:10+10+1=21

    权重相同时,最后定义的样式会起作用


    盒模型

    标准模式:box-sizing:content-box;

    怪异模式:box-sizing:border-box;

    两种模式的区别:

    标准模式会被设置的padding撑开,而怪异模式则相当于将盒子的大小固定好,再将内容装入盒子。盒子的大小并不会被padding所撑开。

    .a a a a

你可能感兴趣的:(【个人笔记】前端开发笔记整理)