• 原生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 是立刻执行

      

          

     

       

  • 相关阅读:
    A/B-test
    LDA概率主题模型
    减肥经验帖
    wide and deep
    利用责任链模式设计一个拦截器
    分享几个 SpringBoot 实用的小技巧
    「造个轮子」——cicada 设计一个配置模块
    「造个轮子」——cicada 源码分析
    「造个轮子」——cicada(轻量级 WEB 框架)
    强如 Disruptor 也发生内存溢出?
  • 原文地址:https://www.cnblogs.com/wanonder/p/7473226.html
Copyright © 2020-2023  润新知