Javascript

[TOC]

继承发展史

原型链:

原型:是function对象的一个属性,定义了构造函数制造出的对象的公共祖先,通过该构造函数产生的对象,可以继承该原型的属性和方法,原型也是对象。
构造函数和普通函数的区别
调用区别:
普通函数的调用方式:直接调用

person();

构造函数的调用方式:需要使用new关键字来调用 new

Person();

构造函数的函数名与类名相同:

Person( );

这个构造函数,Person 既是函数名,也是这个对象的类名
定义:

Person.prototype = {
height: 10000;
width: 1000;
carname: "nn";
}

注意:改了整个空间

Person.prototype.height = 10000;

注意:只改了个值

Person.prototype.name = "";

则所有new出来的Person的后代全部先天带有name属性或者方法,但是可以后天进行改变。

删除属性:

delete person.name; =>true

注意:删除不存在的属性结果也是true

constructor方法:

作用:后代可以通过这个属性来找到他的祖先,通过constructor虽然是系统隐性自带属性但是可以手动更改

prototype通过

__proto__

连接后代和祖先,所以后代所带的祖先原型可以被手动更改,可以换祖先

后代. __proto__=祖先.prototype

原型链的连接点:prototype
弊端:继承太多不想要的东西,没办法进行选择
所有最开始的祖先都有一个自带的

__proto__

原型链里面有很多东西比如toString;
注意:子代可以给祖先加属性,加在后代没有的属性上面,所以会直接给到祖先
son.fortune.name son没有fortune属性,继承自他的祖先,这样写可以添加祖先的fortune属性的属性
son.fortune =》相当于son.fortune = son.fortune +1; 给自己加了一个属性并加1

创建对象方法:
var obj1 = Object.creat(原型)
var obj1 = Objecct.creat(obj);
var person = Object.creat(Person.prototype)
Object.creat(null) =>现在构造出的对象没有原型,

__proto__也没有,再人为去加__proto__,属性后代也是不会继承的

借用构造函数:

弊端:不能继承借用构造函数的原型
每次构造函数都要多走一个函数
call
所有的方法都可以使用call

作用:将这个方法里面所有的this替换成括号内内容

function Person(name,age){}
Person.call(obj,'Wu',300);

在这个Person里面先执行

this==obj

然后Wu和300作为Person的两个参数被传进去
应用:在某一个函数里面用别的函数的东西,很方便:D
apply:
apply(this,实参)
唯一不同:只能传一个实参,所以有多个实参的话要用数组传进去哦,比如[num1,num2]

公有原型:

让两个函数的原型指向同一个原型
弊端:当往一个函数的原型添加属性的时候,另外一个函数也会增加这个属性,因为两个函数的原型现在指向了同一个空间,简单来说现在原型只有一个。

圣杯模型:

公有原型+原型链(一个以公有原型为原型的新构造函数,并使得我们的目标函数成为一个被这个新构造函数new出来的对象)

var inherit = (function(){

var F = function(){};

return function(Target, Origin){

F.prototype = Origin.prototype;

Targrt.prototype = new F();

Target.prototype.constuctor = Target;构造函数

Target.prototype.uber = Origin.prototype;超级父级

}

}());

应用到了闭包,举例:

一个在构造函数里面定义的变量,当该构造函数中有一个方法{将该变量赋给这个构造函数的一个属性};此时调用该构造函数的这个方法可以将定义在函数内部的值通过属性传了出来 =》私有化变量,这个变量是他自己的,除非设置了自己的方法,否则别人根本找不到这个变量。圣杯模型中的构造函数F()就成为了一个私有化变量。

others

  1. 可正常计算的范围小数点前后16位

  2. str.charCodeAt(i) => 求出str的第i位的字符编码

    如果字符编码小于等于255则该位字节长度为1,若大于255则该位字节长度为2

    注意:中文的逗号的占两位噢~英文的逗号占一位

  3. 实现一个构造函数的方法连续调用,只要在每一个方法最后return this就可以实现链式调用模式。

    Person.sex.name.age

    ————7.14

命名空间

闭包

变量私有化,不会污染到全局变量

var init = (function(){

var name = 'abc';

function callName(){

console.log(name);

}

return function(){

callName(); 留下一个以后可以调用的接口

}

}())

init() => abc

对象枚举

属性的表示方法:

(1)Person.name

(2)Person[‘name’] =>用法更灵活,字符串进行拼接作为属性名

for in循环

for(var prop in obj){ prop也可以用其他单词代替,在for in循环中每一圈prop代表一个属性名,用其他单词也是同理;

console.log(prop);

console.log obj[prop]; 注意:prop作为一个变量,不可以使用obj.prop访问

}

hasOwnProperty过滤方法

obj.hasOwnProperty(prop)

作用:辨别该方法是不是这个对象的方法,可以排除方法的方法(也就是一级)返回true,false`

in

判断这个对象上面是否有该属性,一级二级多级的都算

'name' in obj 属性是字符串,要加单引号

instanceof

A instanceof B 判断A对象是不是构造函数B构造出来的(即等同于判断A的原型链上是否有B的原型)

区别 []数组 和 {}对象 的三种方法:

var obj={};

  1. constructor

    [].constructor =>Array

    obj.constructor =>Object

  2. instanceof

    [] instanceof Array =>true

    obj instanceof Array =>false

  3. toString

    Object.prototype.toString.call([]) => object Array

    Object.prototype.toString.call(obj) => object Number

    Object.prototype.toString.call(123) => object Object

Deep Clone

  1. 遍历对象 for(var prop in obj)【一般和hasOwnpropety绑定使用】

  2. 判断是不是原始值 typeof()

  3. 判断是数组还是对象 (三种方法,一般采用toString)

  4. 建立相应的数组或对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function deepClone(origin, target){
var target = target || {},
toStr = Object.prototype.toString, //简短代替
arrStr = "[object Array]"; //为了进行后期比对
for(var prop in origin){
if(origin,hasOwnproerty(prop)){
if(prigin[prop] !== "null" && typeof(origin[prop]) == 'object'){ //判断不为空的引用值
if(toStr.call(origin[prop]) == arrStr){ //判断是否为数组
target[prop] = [];
}
else{
target[prop] = {};
}

deepClone(origin[prop],target[prop]); //递归,进行数组或对象内的克隆

}
else{ //原始值
target[prop] = origin[prop]
}
}
}
return target;
}

三目运算符

条件判断?是:否

JSON

一种用于传输数据的格式

JSON.parse(); string –> json

JSON.stringify(); json –>string

JS异步加载

  1. defer异步加载

    <script type="text/javascript" src="tools.js" defer="defer"></script>

    要等到dom文档全部解析完才会被执行,只有IE能用,也可以将代码写到内部

  2. aysnc异步加载

    <script type="text/javascript" src="tools.js" aysnc="aysnc"></script>

    加载完就执行,aysnc只能加载外部脚本,不能把js写在script标签里面,IE9及以上

  3. 创建script,插入到DOM中,加载完毕之后callBack

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    function loadScript(url,callback){		//按需加载

    var script = document.creatElement('script');
    script.type = "text/javascript"; //下载需要时间,并不能马上用引入的JS中的方法,还没下载完呢

    if(script.readyState){ //存在状态码的时候
    script.onreadystatechange = function(){ //IE 监听状态码是否改变
    if(script.readyState == "complete" || script.readyState == "loaded"){
    callback(); //当状态码发生改变,从loading变成complete或loaded时,script下载完成,可以执行别的内容了
    }
    }

    }

    else{
    script.onload = function(){ //Safari chrome firefox opera
    callback(); //当script 确保下载完再进行执行
    }

    }
    script.src = url; //传进来的url带双引号,放在尾部可以防止状态码改变事件不被触发
    document.head.appendChild(script);
    }


    //引用的话需要用匿名函数
    loadScript('demo.js',text());//报错,因为未解析JS文件呢,哪能识别到JS里面的text是啥
    loadScript('demo.js',function(){//使用匿名函数,函数体内部只有当被执行的时候才会被读取,就是要用到他的时候才去识别他
    text();
    })

JS加载时间线

​ 1.创建Document对象,开始解析web页面,解析HTML元素和他们的文本内容后添加Element对象和Text节点到文档中。这个阶段Documen.readyState = "loading"。

​ 2.遇到link外部css,创建线程加载,并继续解析文档。

​ 3.遇到script外部js,并且没有设置asyncdefer ,浏览器加载,并阻塞,等待js加载完成并执行该脚本,然后继续解析文档

​ 4.遇到script外部js,并且设置有asyncdefer 浏览器创建线程加载,并继续解析文档,对于async属性的脚本,脚本加载完成后立即执行(异步禁止使用docuemnt.write())。

​ 5.遇到img标签等,先正常解析dom结构,然后浏览器异步加载src,并继续解析文档

​ 6.当文档解析完成,document.readyState = "interactive";

​ 7.文档解析完成后,所有设置有defer的脚本会按照顺序执行。注意和async的不同,但同样禁止document.write()

​ 8..当文档解析完成之后,document对象触发DOMContentLoaded事件,这也标志着程序执行从同步脚本执行阶段,转化为事件驱动阶段

​ 9.当所有saync的脚本加载完成并执行后,img等加载完成后,document.readyState = "complete" window对象触发load事件

​ 10.从此,页面以异步响应方式处理用户输入,网络事件等。

window.onload //当页面全部加载完才执行

document.addEventListener('DOMContent',function(){

},false) //dom解析完就执行的部分

垃圾加载回收机制和内存泄漏

垃圾加载回收机制Garbage Collection:执行环境负责管理代码执行过程中使用的内粗,垃圾收集器会定期找出那些不再继续使用的变量,然后释放内存。

内存泄漏:不再用到的内存,没有及时释放

垃圾回收策略

标记清除:对脱离作用域的变量进行回收,当进入作用域时,进行标记,离开作用域的时候,标记并回收这些变量。各大浏览器实现的都是标记清除的垃圾回收策略或者类似的策略,但是垃圾收集的时间间隔互不相同。

引用计数:跟踪记录每个值被引用的次数,被引用一次则加1,当这个引用计数为0时,被视为准备回收的对象,每过一段时间开始垃圾回收的时候,就把被引用数为0的变量回收。这种方法很容易引起内存泄漏,如即使两个对象都离开了作用域,但是只要它们的引用次数不是0,它们还会继续存在。

常见内存泄漏的原因

  1. 全局变量引起的内存泄漏
  2. 闭包引起的内存泄漏
  3. dom清空或者删除时,时间未清除导致的内存泄漏
  4. 循环引起的内存泄漏