zoukankan      html  css  js  c++  java
  • 北京MedPeer凉经

    一、请说出三种不同含义的this使用场景

      1.作为对象方法调用

        在 javascript 中,函数也是对象,因此函数可以作为一个对象的属性,此时该函数被称为该对象的方法,在使用这种调用方式时,this 被自然绑定到该对象

    var test = {
        a:0,
        b:0
        get:function(){
            return this.a;
        }
    }
    

      2.作为全局变量使用

        函数也可以直接被调用,此时 this 绑定到全局对象。在浏览器中,window 就是该全局对象。比如下面的例子:函数被调用时,this 被绑定到全局对象,接下来执行赋值语句,相当于隐式的声明了一个全局变量。

    var x = 10;
    function foo() {
      console.log(this); //Window
      console.log(this.x); //10
    }
    foo();
    

      3.作为构造函数调用

       javascript 支持面向对象式编程,与主流的面向对象式编程语言不同,javascript 并没有类(class)的概念,而是使用基于原型(prototype)的继承方式。相应的,javascript 中的构造函数也很特殊,如果不使用 new 调用,则和普通函数一样。作为又一项约定俗成的准则,构造函数以大写字母开头,提醒调用者使用正确的方式调用。如果调用正确,this 绑定到新创建的对象上。

    function Foo() {
      this.x = 10;
      console.log(this); //Foo {x:10}
    }
    var foo = new Foo();
    console.log(foo.x); //10
    

      4.在call、apply、bind中调用

        当一个函数被 call、apply 或者 bind 调用时,this 的值就取传入的对象的值。

    var obj = {
      x: 10,
    };
    function foo() {
      console.log(this); //{x: 10}
      console.log(this.x); //10
    }
    foo.call(obj);
    foo.apply(obj);
    foo.bind(obj)();
    

      5.作为DOM节点

        在一个 html dom 事件处理程序里,this 始终指向这个处理程序所绑定的 html dom 节点

    function Listener() {
      document.getElementById('foo').addEventListener('click', this.handleClick); //这里的 this 指向 Listener 这个对象。不是强调的是这里的 this
    }
    Listener.prototype.handleClick = function(event) {
      console.log(this); //<div id="foo"></div>
    };
    var listener = new Listener();
    document.getElementById('foo').click();
    

      6.箭头函数中的this

        箭头函数内部的 this 是词法作用域,由上下文确定。

    var obj = {
      x: 10,
      foo: function() {
        var fn = () => {
          return () => {
            return () => {
              console.log(this); //Object {x: 10}
              console.log(this.x); //10
            };
          };
        };
        fn()()();
      },
    };
    obj.foo();
    

      以上是六种this的使用环境,原文链接

    二、编程题

      实现一个获取当前页面链接search值的函数。(如下例子中,输入key1输出value1)例:’http://test.com/index?key1=value1&key2=value2’

      思路:需要根据key找到value,首先将?后面拼接的参数提取出来,然后将其转为对象形式,再按键取值

      实现:使用DOM中location对象的属性+substr+split方法获取键值对数组,再遍历数组将里面的key1=value1通过等号分开,再存入对象中

    var arr = window.location.search.substr(1).split("&")
    var obj={}
    for(var i=0;i<arr.length;i++){
    	var key = arr[i].split('=')[0]
    	var value = arr[i].split('=')[1]
    	obj[key]=value
    }
    var str = prompt('请输入键')
    console.log(obj[str])

    三、说一下你对原型链的理解、应用场景、以及下面代码报错原因

    function  Dog(name)  {  
    this.name  =  name
    }
    Dog.bark  =  function()  {
        console.log(this.name  +  '  says  woof')
    }	
    let  fido  =  new  Dog('fido');
    fido.bark()

      理解:在javascript里面,每个对象都有一个prototype属性,指向它的原型对象.这个原型对象里面同时还有自己的原型,原型一环扣一环,直到某个对象的原型为null,这一级一级的链结构就是原型链。

      应用场景:js通过原型链实现函数或对象的继承

      报错原因:fido这个对象并没有bark方法。代码中虽然给dog对象绑定了bark方法,但是绑定的是静态方法,调用形式只能通过dog.bark去调用。Fido并没有继承这个方法,所以会报错。

      Ps:如果需要fido.bark()不报错。可以在dog函数的内部写this.bark=function(){}或者在绑定bark方法时,使用Dog.prototype.bark=function(){}

    四、什么是事件委托、简述它的作用和原理

      概念:事件委托就是事件目标(子元素)不处理事件,把事件委托给父元素去处理。

           作用:1、减少页面绑定事件的数量,提高页面的性能

                      2、可以灵活的处理子节点动态变化的场景,无论子节点增加还是减少,事件都无需重新绑定

           原理:利用事件冒泡,将事件加在父元素或者祖先元素上,触发该事件。

     五、下面的代码执行结果是什么,请说明理由

    function  greet(person)  {
        if  (person  ==  {  name:  'amy'  })  {
            return  'hey  amy'
        }  else  {
            return  'hey  arnold'
        }
    }
    greet({  name:  'amy'  })
    

        执行结果在控制台打印出'hey  arnold'。greet方法传入一个对象时,与内部的对象{  name:  'amy'  }进行==判断,尽管这两个对象的结构、键值相同,但是他们的地址不同,所以返回flase,执行了else语句里面的代码,返回了'hey  arnold'

    六、写出下面代码执行后正确顺序的输出结果以及原因解析

    var a=1;
    function fun1(){
    console.log(a);
    }
    function fun2(){
    console.log(a);
    var a=2;
    console.log(a);
    }
    fun1();
    fun2();
    console.log(a);
    

      原因:首先执行fun1()函数,因为已经有全局变量a=1,所以打印出1,然后执行fun2()函数,函数内部存在变量提升,函数内部实际执行顺序:

    var a;
    console.log(a)//undefined;
    a=2;
    conosle.log(a)//2
    

      所以打印出undefined和2,最后在执行console.log(a),这里仍然打印出的是全局变量a的值,所以是1

    七、写出下面代码执行后正确顺序的输出结果以及原因解析

    var a=1;
    console.log(1);
    setTimeout(function () {
        console.log(2);
    },0);
    function fun() {
        console.log(3);
        setTimeout(function () {
            console.log(4);
        },0);
        for (var i=0;i<10000;i++){
            a++;
        }
        console.log(5);
        return a;
    };
    console.log(6);
    console.log(fun());
    

      正确输出顺序1 6 3 5 10001 2 4

      原因:

             按照顺序执行代码,先打印出1,然后遇到第一个setTimeout,会将其存放到异步队列,等待主线程执行完成之后才会执行。然后打印6,再执行fun函数。Fun函数内部首先打印出3,然后遇到第二个setTimeout,也将其放入异步队列。,再执行for循环,for循环内部a的最终值是10001。然后打印5,再返回a,打印a的值为10001。此时主线程执行完毕,执行先前存放的setTimeout。又因为队列是先进先出,所以先打印2再打印4。

    八、JS的基本数据类型有哪些

      7种:Boolean Null Undefined Number String Symbol(ES6) BigInt (ES10)

    九、vue的双向数据绑定原理

      首先要对数据进行劫持监听,vue设置了一个监听器observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者watcher看是否需要更新。因为订阅者是有很多个,vue设置了一个消息订阅器dep来专门收集这些订阅者,然后在监听器observer和订阅者watcher之间进行统一管理的。接着,我们还需要有一个指令解析器compile,对每个节点元素进行扫描和解析,将相关指令对应初始化成一个订阅者watcher,并替换模板数据或者绑定相应的函数,此时当订阅者watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。(后面复习vue的时候我会单独写一篇文章解释,这个就先放到这里,不全面!)

     十、原生js如何实现双向数据绑定

       这篇文章非常详细了,传送门

    十一、如何监听多个promise的执行状态以及promise的应用场景

      使用promise.all()方法,promise.all(iterable) 方法返回一个 promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果

      应用场景:js异步编程的新方案,解决了以往的回调嵌套回调出现回调地狱的问题

    十二、DOM节点的增删改查,getElementBy和querySelector获取DOM节点的区别

      DOM的增删改查就不再赘述了,传送门。详细的说一下getElementBy和querySelector的区别

      1.W3C标准

        queryselectorall 属于 w3c 中的 selectors api 规范 。而 getelementsby 系列则属于 w3c 的 dom 规范 。(了解)

      2.浏览器兼容

        queryselectorall 已被 ie 8+、ff 3.5+、safari 3.1+、chrome 和 opera 10+ 良好支持 。getelementsby 系列,以最迟添加到规范中的 getelementsbyclassname 为例,ie 9+、ff 3 +、safari 3.1+、chrome 和 opera 9+ 都已经支持该方法了。

      3.接收参数

        querySelectorAll 方法接收的参数是一个 CSS 选择符。而 getElementsBy 系列接收的参数只能是单一的className、tagName 和 name。代码如下:

    var c1 = document.querySelectorAll('.b1 .c');
    var c2 = document.getElementsByClassName('c');
    var c3 = document.getElementsByClassName('b2')[0].getElementsByClassName('c');
    

        需要注意的是,queryselectorall 所接收的参数是必须严格符合 css 选择符规范的。所以下面这种写法,将会抛出异常。(css 选择器中的元素名,类和 id 均不能以数字为开头。)代码如下:

    try {
      var e1 = document.getElementsByClassName('1a2b3c');
      var e2 = document.querySelectorAll('.1a2b3c');
    } catch (e) {
      console.error(e.message);
    }
    console.log(e1 && e1[0].className);
    console.log(e2 && e2[0].className);
    

      4.返回值(获取的结点)

        大部分人都知道,queryselectorall 返回的是一个static node list,而 getelementsby 系列的返回的是一个Live Node List。

    // Demo 1
    var ul = document.querySelectorAll('ul')[0],
        lis = ul.querySelectorAll("li");
    for(var i = 0; i < lis.length ; i++){
        ul.appendChild(document.createElement("li"));
    }
    
    // Demo 2
    var ul = document.getElementsByTagName('ul')[0], 
        lis = ul.getElementsByTagName("li"); 
    for(var i = 0; i < lis.length ; i++){
        ul.appendChild(document.createElement("li")); 
    }
    

        因为 demo 2 中的 lis 是一个动态的 node list, 每一次调用 lis 都会重新对文档进行查询,导致无限循环的问题。 而 demo 1 中的 lis 是一个静态的 node list,是一个 li 集合的快照,对文档的任何操作都不会对其产生影响。

        至于为什么queryselectorall拿到的是一个快照,源自W3C的规定【the nodelist object returned by the queryselectorall() method must be static ([dom], section 8)】

      ps:queryselectorall 的返回值是一个静态的 nodelist 对象,而 getelementsby 系列的返回值实际上是一个 htmlcollection 对象 。nodelist 对象会包含文档中的所有节点,如 element、text 和 comment 等。 htmlcollection 对象只会包含文档中的 element 节点。

      5.性能

        因为queryselectorall返回一个静态的nodelist(深克隆) getelementby系列返回一个动态的实时变化的nodelist(htmlcollection)(浅克隆,每次都返回一个指针) 所以queryselectorall会降低性能

    十三、总结

      由于一直没来得及复习,js还没开始,不过老本已经不够吃了,需要加油啊,很多基础的东西都忘记了。还有一部分问题,我打算放到其他复习文章里面,就不在这里说了

        

        

     

  • 相关阅读:
    数据库unsigned char*类型图片存进
    int main(int argc, char *argv[])中的argc和argv
    数据库任务进度记录
    数据库存入数据后id保持不变,或者直接报错
    数据库图片存入并显示成功,但查询时不能全显示
    数据库存入图片成功但显示不出来
    JWT(Json web token)认证详解
    重启eclips后启动项目出现监听文件找不到
    解决服务器连接错误Host ‘XXX’ is not allowed to connect to this MySQL server
    Linux系统常用命令
  • 原文地址:https://www.cnblogs.com/spoem/p/13255459.html
Copyright © 2011-2022 走看看