JS笔试遇到的知识点(3)

运算符优先级

参考MDN的运算符优先级中的“汇总表”


位运算符&|

  • 参考
  • &,按位与运算符,参加运算的两个数据,按二进制位进行”与”运算。两个 位 都为1时,结果才为1
    • 0&0=0 0&1=0 1&0=0 1&1=1
    • 3&50011 & 0101 = 0001,因此 3&5 的值是1
  • |,或,两个位只要有一个为1,那么结果都为1,全为0才得0
    • 0|0=0 0|1=1 1|0=1 1|1=1
    • 3|50011| 0101 = 0111,因此,3|5的值得7。

逻辑运算符&&||的规律

  • 可参考MDN的逻辑运算符逻辑运算符
  • 明确:&&||返回的是表达式,!返回的是布尔值!
  • 会被转换为 false 的表达式有
    • null; NaN; 0; 空字符串("" or '' or ``); undefined。
  • 帮助理解
    返回表达式的原则:从前往后判断,只要到了能判断出 整个表达式的真假 的位置就停下来返回这个位置的部分表达式。
  • &&:前后都为真才是真,只要有一个是假的就是假。所以只要有第一个表达式是假的我们就不用继续判断了,返回第一个表达式。如果第一个表达式是真的我们就继续判断第二个表达式,(但由于一定要返回一个表达式,所以)此时无论真假都得返回第二个表达式。
  • ||:只要有一个是真就是真。所以只要有第一个表达式是真的就可以判断整个表达式都是真的,故返回第一个表达式。如果第一个表达式是假的那我们就要继续判断第二个表达式,(但由于一定要返回一个表达式,所以)此时无论真假都得返回第二个表达式。
  • 例子
    1
    2
    3
    4
    5
    //10可被强转为true0则是false,有一个错的就返回错的表达式
    console.log(10 && 0);//0
    //""可被强转为false,"abc"可被强转为true,有一个是真的就返回真的表达式
    console.log("" || "abc");//"abc"
    console.log(!window.abc);//true。`window.abc`是undefined,强转为false

题目

  • 问题1 && 2>1返回的布尔值?
  • 答案:true
  • 解析
    >的优先级排在前,所以先判断右边的表达式,2>1 结果为true。得到1&&true ,1可被强转为true,前真后真返回后,所以返回的结果是 运算符后面的表达式 ,也就是true。
  • 改一下问题console.log(2 > 1 && 1);
  • 答案:1
  • 解析
    2>1 结果为true,所以返回 运算符后面的表达式,也就是1.

cookie的生命期

  • cookie的有效时间expires/Max-Age不设置的话默认值是Session【-1?】,意思是cookie会和session一起失效。当浏览器会话关闭(不是浏览器标签页,而是整个浏览器) 后,此cookie失效
  • 可以通过cookie.setMaxAge()方法(单位:秒)设置cookie的生命期。不过这个方法基本舍弃了。
    • cookie.setMaxAge(0)表示立刻删除该浏览器上指定的cookie。
    • 使用expires为 cookie 添加一个过期时间(以 UTC 或 GMT 时间)document.cookie="expires=Thu, 18 Dec 2043 12:00:00 GMT";

Ajax技术的工作原理(XMLHttpRequest)

  • 可参考笔记AJAX异步更新
  • Ajax技术核心就是XMLHttpRequest对象。
  • Ajax技术的工作原理(可以分成3步):
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //1. 创建XMLHttpRequest对象:
    var xhr = new XMLHttpRequest();
    //2. xhr 发送请求:
    xhr.open('get','test.html','true');
    xhr.send();
    //3. xhr获取响应:
    xhr.onreadystatechange = function(){
    if(xhr.readystate == 4){//请求的状态码
    /*
    0:请求还没有建立(open执行前)
    1:请求建立了还没发送(执行了open)
    2:请求正式发送(执行了send)
    3:请求已受理,有部分数据可以用,但还没有处理完成
    4:请求完全处理完成
    */
    alert(xhr.responseText);//返回的数据
    }
    }
  • 可以看到,send()前是open()
  • 在笔记“AJAX异步更新的向服务器发送请求”中也提到:AJAX异步更新 步骤

解释型语言的特性:非独立、效率低

  • 解释型语言:Python/JavaScript等。
  • 非独立:JavaScript语言依赖执行环境,对于客户端来说是浏览器,对于服务端来说是node。
  • 效率低:执行前不需要编译,执行时才编译,因此效率低。

解释性语言和编译性语言

  • 计算机不能直接理解高级语言,只能直接理解机器语言,所以必须要把高级语言翻译成机器语言,计算机才能执行高级语言编写的程序。
  • 翻译的方式有两种,一个是编译,一个是解释。两种方式只是翻译的时间不同。
  • 主要区别:编译性语言编译后即可在该平台运行,解释性语言是在运行期间才编译。所以编译性语言运行速度快,解释性语言跨平台性好
  • 解释性语言
    • 定义:解释性语言的程序不需要编译,在运行程序的时候才翻译,每个语句都是执行的时候才翻译。这样解释性语言每执行一次就需要逐行翻译一次,效率比较低。
    • 比如:JS、python
    • 现代解释性语言通常把源程序编译成中间代码,然后用解释器把中间代码一条条翻译成目标机器代码,一条条执行。
  • 编译性语言
    • 定义:编译性语言写的程序在被执行之前,需要一个专门的编译过程,把程序编译成为机器语言的文件,比如exe文件,以后要运行的话就不用重新翻译了,直接使用编译的结果就行了(exe文件),因为翻译只做了一次,运行时不需要翻译,所以编译型语言的程序执行效率高。
    • 比如:c
  • java既可以算解释性语言也可以算编译性语言。

动态语言与静态语言

  • JavaScript是动态语言(弱类型语言)。
  • 静态语言(强类型语言):
    • 静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型
    • 例如:C++、Java、Delphi、C#、Objective-C等
  • 动态语言(弱类型语言):
    • 动态语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。
    • 例如:PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等

区别 字符串字面量 和 String对象

  • 首先注意:typeof来判断数据类型其实并不准确。比如数组、正则、日期、对象的typeof返回值都是object,这就会造成一些误差。
  • 准确判断可以从构造函数(instanceof)原型链(prototype.isPrototypeOf)上下手,具体可以看笔记 JS数据类型
  • JS 中值的类型分为原始值类型和对象类型
    • 原始值类型包括 number, string, boolean, null 和 undefined;(记忆:纳尼USB)
    • 对象类型即 object。首先明确原始值类型不是对象
  • 另外,要注意 "hello"new String('hello') 的区别,前者是字符串字面值,属于 值类型 ,而后者是对象
    用 typeof 运算符返回的值也是完全不一样的:
    1
    2
    12 typeof 'hello';// 'string'
    typeof new String('hello');// 'object'
  • 很多人分不清字符串字面值和 String 对象,是因为 JS 的语法中的“装箱”:
    • 当执行 'hello'.length 时,返回 5,很多人就觉得 'hello' 就是 String 对象,不然它怎么会有 String 对象的属性。
    • 其实,这是由于 JS 在执行到这条语句的时候,内部将 'hello' 包装成了一个 String 对象,执行完后,再把这个对象丢弃了,这种语法叫做 “装箱”,在其他面向对象语言里也有(如 C#)。
      不要认为 JS 帮你装箱了,你就可以在写代码的时候不分箱里箱外了!
      【题目可看20200205第十题】

Array.sort()升序/降序排序的函数规则

  • sort()方法可以接收一个比较函数作为参数.(该比较函数为含有两个参数的匿名函数)
  • 注意:sort()是直接改变原数组的
  • 例子以及详细笔记在这
1
2
3
4
5
6
7
var arr=[9,23,15,-99,88,12,-2];
//降序
arr.sort(function(a,b){return b-a});
console.log(arr);//[88, 23, 15, 12, 9, -2, -99]
//升序
arr.sort(function(a,b){return a-b});
console.log(arr);//[-99, -2, 9, 12, 15, 23, 88]

JS模块化(CommonJS,AMD,CMD)

  • 主流的模块化包括 CommonJS,AMD,CMD 等。
  • 模块化有利于管理模块间的依赖,更依赖模块的维护
  • CommonJS是服务器端的js模块化规范,同步的。
    • NodeJS就采用这个规范。
  • AMD和CMD都是浏览器端的js模块化规范,是异步的。
    • Require.JS遵循AMD规范,Sea.js遵循CMD规范
    • AMD推崇依赖前置,CMD推崇依赖就近

AMD和CMD

  • AMD异步模块定义(”Asynchronous Module Definition”)。
  • 它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
  • AMD也采用require()语句加载模块,但是不同于CommonJS。
  • 主要有两个Javascript库遵循AMD规范:require.js和curl.js

AMD和CMD的区别

  1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行
  2. CMD 推崇依赖就近,AMD 推崇依赖前置

angularjs1中的$apply()【待补充】

$apply 是为了让angularJS内部没有在$digest状态当中的代码块进入到$digest当中,从而实现双向数据绑定。所谓$digest就是angularjs 检测数据更新的方式。 例如setTimeout这类延迟函数angularjs不会去去自动运行$digest来绑定数据。从而无法实现其效果(仅是双向数据绑定效果)一般安全使用方法:

1
2
3
if($scope.$$phase){  //返回$digest状态
$scope.$apply
}

函数的调用方式

  • 直接调用
  • 作为对象方法调用
  • 作为构造函数调用
    • 要以构造函数的方式调用函数,只需要在调用时加new 关键字.
      • 比如:function whatsMyContext(){ return this; };
      • 调用:var one = new whatsMyContext();
    • (可参考这篇博客)
  • 通过call和apply方法调用image.png

可用作JS异步编程的方法

  • 这里
  • 回调函数,这是异步编程最基本的方法。
    • 例:假定有两个函数f1和f2,后者等待前者的执行结果,如果f1是一个很耗时的任务,可以考虑改写f1,把f2写成f1的回调函数。【此时f2是异步的,她耗费的时间并不影响同步任务的执行】
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      function f2() {
      console.log("f2");
      }
      console.log("start");
      function f1(callback) {
      console.log("f1");
      setTimeout(function () {
      callback();
      }, 1000);
      }
      f1(f2);
      console.log("end");
      // start f1 end f2
  • 事件监听,任务的执行不取决于代码的顺序,而取决于某个事件是否发生。
    • 例:为f1绑定一个事件,当f1发生done事件,就执行f2。
  • 发布/订阅,与”事件监听”类似。
    • 我们假定,存在一个”信号中心”,某个任务执行完成,就向信号中心”发布”(publish)一个信号,其他任务可以向信号中心”订阅”(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做”发布/订阅模式”(publish-subscribe pattern),又称”观察者模式”(observer pattern)。
    • 这种方法的性质与”事件监听”类似,但是明显优于后者。因为我们可以通过查看”消息中心”,了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。
  • Promises对象,Promises 对象是CommonJS 工作组提出的一种规范,目的是为异步编程提供统一接口。
    • 简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。回调函数变成了链式写法,程序的流程可以看得很清楚,而且有一整套的配套方法,可以实现许多强大的功能。
    • 例:f1的回调函数f2,f1().then(f2);

,