原生JS知识点

1、 JS的变量类型

   JS可以识别7种不同类型的值

        简单类型:Boolean Number Strng null undefined Symbol (ES6新增,一种数据类型,它的实例是唯一且不可改变的)

        复杂类型:Object

       两种类型的区别是:存储位置不同;

         原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;

   引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;

   引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体

       

     typeof: number 、string、boolean 、undefined、function 、object ( 对象、数组、null )、symbol       ( 7种 )

     

   

 

2、== 和 === 的区别 以及 == 如何隐式转换?

     === 、  !==判别方式:

     1、不同类型,直接false

     2、原始类型值相同,返回true

     3、 复合类型(对象、数组、函数)的数据比较时,看它们是否指向同一个对象

     4、undefined 和 null 与自身严格相等

   ==、!= 判别方式

    1、布尔值会在比较之前转换成数值 false-0 true-1

    2、 如果一个操作数是字符串,另一个是数值,比较之前将字符串转换成数值

   3、如果一个操作数是对象,另一个不是,则调用对象的valueOf()方法,再用基本类型值按照之前的规则进行比较     

1 var str2 = new String("http://www.365mini.com");
2 console.log(str2.valueOf() == "http://www.365mini.com") 

    4、 null 和 undefined 是相等的

    5、 比较之前不能将null  和 undefined 转换

    6、NaN 不等于任何值,包括他自己

    7、如果两个操作数都是对象,则比较它们是不是同一个对象,如果都指向同一个对象,则为true, 否则为false

3、undefined 和 null  的区别

     null 用来表示尚未存在的对象,常用来表示函数企图返回一个不存在的对象 ,转换成数值 0。对象原型链的终点。

     undefine 表示变量已经声明,但还没赋值的时候 默认值为 undefined,转换成 NaN, 函数没有返回值时,默认返回undefined

 

4、JS 如何实现继承

  总共有6种方法    分为构造函数的继承 和  普通对象的继承

      1.原型链继承       缺点:一个实例改变了引用类型的属性,其他实例都会发生改变

 1  function Subtype(){
 2      this.age = 2;
 3   } 
 4  function Supertype() {
 5      this.name = 'sansa'
 6   }
 7  Subtype.prototype = new Supertype(); //此时subtype.prototype的已经有了supertype的属性
 8 
 9  var s = new Subtype();
10  s.name  //sansa

  2.借用构造函数继承      缺点:函数无法复用,每调用一次都会创建一个函数对象---

 1 function Supertype(name){
 2    this.colors = ["red","yellow"];
 3    this.name = name;
 4 }
 5 
 6 function Subtype(){
 7    Supertype.call(this,'hehe');  //关键代码  直接在子类型中调用超类型的构造函数  这样只能得到构造函数中的属性,无法连接到原型链   比较粗暴,优点是可以传值
 8 }
 9 var ss = new Subtype();
10 
11 ss.name //hehe

  3.组合继承(原型+借用构造)     缺点:构造函数继承的属性(出现在subtype实例中),在原型链中又会重新继承一次(出现在subtype.protype属性中)

       将上面两种结合,构造函数中继承 个性属性(例如数组属性),原型链中继承 函数

 

  4.原型式继承 (普通对象继承,ES5中的 Object.create() )   缺点:和原型链继承一样,数组属性 会被改变--

1 function object(o) {
2    function F(){}
3    F.prototype = o;      //返回的是 F 的实例,而F的 prototype 指向的是o , 实例本身没有属性,都是靠原型链继承的--   
4    return new F();
5 }

  这个object()函数,其实只做一件事,就是把子对象的prototype属性,指向父对象,从而使得子对象与父对象连在一起。

     

  5.寄生式继承

function createAnother (original) {
   var clone = object(original);
   clone.sayHi = function() {
   console.log('hi');   
}    
   return clone;       //挂羊头卖狗肉---- 本质还是原型式继承
}

 

  6.寄生组合式继承  

        为了解决组合继承的缺点(继承了两次基本属性--)  原理:不必为了指定子类型的原型而调用超类型的构造函数,重新改写 原型链那一段

1 function inheritPrototype(subtype,supertype){
2    var prototype = object(subpertype.prototype);
3    prototype.construcor = subtype;            //prototype 上除了constructor 没有其他属性,唯一的作用就是作为连接桥梁
4    subtype.prototype = prototype;   
5 }

     顺便看看阮一峰的深拷贝--

     浅拷贝只是遍历父元素的属性,然后赋给 子元素 ,如果父元素中有引用类型的属性,子对象拿到的是一个内存地址, 子对象会改变父对象的引用属性

     深拷贝:实现真正意义上数组和对象的拷贝。递归调用"浅拷贝     

 1 function deepCopy(p,c) {
 2     var c = c || {};
 3     for(var i in p) {
 4         if(typeof p[i] === 'object') {
 5             c[i] = (p[i].constructor === Array) ? [] : {};
 6             deepCopy(p[i],c[i]);
 7         } else {
 8             c[i] = p[i];
 9         }
10     }
11
12     return c;
13 }

 

5、new 操作符具体干了些什么

  1、创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。

  2、执行函数,上下文this 会指定为这个新实例对象

  3、如果构造函数返回了一个对象,则这个对象会取代new出来的结果,否则会返回这个实例对象 新创建的对象由 this 所引用,并且最后隐式的返回 this 。

1 var new2 = function(func){
2     var o  = Object.create(func.prototype);
3     var k  = func.call(o);
4     if(typeof k === Object) {
5     return k
6     } else {
7     return  o;
8     }
9 }

 

6、 This 用法  

  this 用法提了很多次,但是对某些点总是有些模糊   (注意:一定要分析真正的调用位置,因为它决定了 this 的绑定); 

       基本的四种不必再多说 ---

  在函数默认绑定中:如果在函数内部加上 'use strict' ,this 会绑定到undefined

  隐式绑定: 对象属性只有上一层或者 最后一层 在调用位置中起作用

 1 function foo() {
 2     console.log(this.a);
 3 }
 4 var obj2 = {
 5     a:52,
 6     foo:foo
 7 }
 8 
 9 var obj1 = {
10     a:2,
11     obj2:obj2
12 }
13 obj1.obj2.foo()  //52  起作用的是 obj2

  同样也很有可能会绑定到全局对象中,看到底是谁在调用   例如:

1 var bar = obj2.foo; // obj2 是上面的-
2 var a = 22;
3 bar(); //22

 setTimeout(obj.foo,100) 也是会绑定到全局对象

显示绑定:

   优先级: new > 显式 > 隐式 > 默认

 

 箭头函数:本身没有  arguments、this,与外层的函数保持一致   因为没有 this, apply.call.bind等方法都无效,  当然也不能做构造函数---

  

7、创建对象

   马克飞象上面已经有写的比较详细了--所以就懒得再写了

 

8、JS 的垃圾回收机制

  8.1 标记清除(最常用的垃圾收集方式)

    当变量进入环境时,将这个变量标记为“进入环境”,离开环境时,将其标记为 离开环境。先给存储在内存中的所有变量都加上标记,然后删除处在环境中的变量以及被环境变量引用的变量的标记,剩下的就是无法再访问的变量,销毁那些带标记的值并回收

它们的内存空间--

  8.2 引用计数    跟踪记录每个值被引用的次数

    当声明了一个变量 被将一个引用类型赋给该变量时,这个值得引用次数就是1 ,变量被赋给另一个值时,这个引用类型就要减1,当为0 的时候即没有办法再访问这个值,则回收内存空间

 

9、JS 合并后与合并前哪个快

     多数浏览器使用单一进程来处理JS脚本执行,所以在解析和执行脚本时,浏览器会停止处理页面.

     在script 标签里面加上 defer 或者是 async ,会异步并行加载脚本,下载时不会阻塞脚本

     defer 是在等待页面完成之后执行, async 是立刻执行

  

      

 

   

posted @ 2017-09-04 13:37  wander的九号球  阅读(978)  评论(0编辑  收藏  举报