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

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实现事件代理
<ul id="parentList">
  <li id="post-1">1</li>
  <li id="post-2">2</li>
</ul>

<script>

  function delegateEvent(interfaceEle,type,fn) {
    if(interfaceEle.addEventListener) {
      interfaceEle.addEventListener(type,fn);
    } else {   //IE
      interfaceEle.attachEvent("on"+type,fn);
    }
  }

var parentList = document.getElementById("parentList");

delegateEvent(parentList,"click",function(e){
  var e = e || window.event;   //兼容IE
  var target = e.target || e.srcElement;   //兼容fireFox
  alert(target.id);   
});

</script>

这段代码监听了整个<ul>标签并且启用了事件代理,点击<li>标签的时候会返回具体的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需要写成以下形式才能被识别

<script>
  //<![CDATA[
    //内容
  //]]>
</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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 在线阅读 http://interview.poetries.top[http://interview.poetr...
    程序员poetry阅读 114,222评论 24 450
  • 1.几种基本数据类型?复杂数据类型?值类型和引用数据类型?堆栈数据结构? 基本数据类型:Undefined、Nul...
    极乐君阅读 5,496评论 0 106
  • 长街融融日,小楼淡淡风,这样的日子适合写信。 铺开素静的白纸,拈起笔来放在唇边咬了咬,缺发现可以倾诉的人寥寥无几。...
    唯有孤阅读 393评论 0 0
  • 很早以前能沟通的工具就是信封。直到现在信息网络的发达更多人用微信。话语轻而易举的说出,更多深刻深沉的话语却无法表达...
    lilinjuan阅读 324评论 0 1
  • 我们是这个世界中忙碌的人群 习惯着每天看同样的风景 习惯着每天走一样的路 习惯着每天 在自己的生活里兜兜转转 而我...
    亲爱的小千阅读 347评论 0 0