陕西队西北狼

JavaScript 基础知识

8.JavaScript 基础知识

一、基础

1、如何理解闭包?

  • 1)定义: 闭包就是能够读取其他函数内部变量的函数。简单说来,可以理解把闭包理解为“定义在一个函数内部的函数”

      function f1() {
        var n = 999;
        function f2() { console.log(n); }
        return f2;
      }
    
      var result = f1();
      result(); // 999
    
      //1)上述代码中的 f2 函数就是一个闭包。
      //2)由于链式作用域的原因,f2 可以访问 f1内定义的变量,反之则不行
      //3)把f2作为返回值,就可以在f1外部读取它的内部变量。
    
  • 2)闭包的用途:

    • 可以读取函数内部的变量。

    • 让这些变量始终保存在内存中。

        function f1() {
          var n = 999;
          nAdd = function () { n += 1 }
          function f2() { console.log(n) }
          return f2;
        }
      
        var result = f1();
        result(); // 999
        nAdd();
        result(); // 1000
      
        //原因:f1中的局部变量n 一直在内存中,并没有在f1调用后被自动清除。
        //因为f1是f2的父函数,而f2被赋给了一个全局变量,导致f2始终在内存中,而f2的存在依赖f1,因此f1也始终在内存中,最终都不会再调用结束被垃圾回收机制回收。
        //此处注意,nAdd也是一个闭包,它被挂载在全局变量下。
      
  • 3)使用闭包注意点:

    • 不能滥用闭包,会造成性能问题,IE中可能导致内存泄漏。解决办法是在退出函数之前,将不用的局部变量全部删除。
    • 如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

2、this 的用法

  • 定义: this 是JavaScript 语言的一个关键字,它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用。

  • 简单来讲:this 就是函数运行时所在的环境对象,即谁调用函数就指向谁。

  • 案例:

      // 1)this 代表全局对象,因为test 调用时挂载在全局对象下,故this代表全局对象
      var x = 1;
      function test() { console.log(this.x); }
      test(); //1
    
      // 2)对象方法调用, 此时this指向 obj,因为调用时是obj 在调用
      function test() { console.log(this.x); }
      var obj = {}
      obj.x = 1;
      obj.m = test;
      obj.m(); // 1
    
      // 3)构造函数调用, new时生成一个新对象,此时this就指向新对象
      var x = 2;
      function test() { this.x = 1; }
      var obj = new test();// this会指向新对象,不会指向全局对象
      console.log(x);  // 2
    
  • apply调用: (apply 是函数的一个方法,作用是改变函数的调用对象)

      用法:apply(thisObj, [args]); // [args] 是一个数组或类数组,是一个参数列表
      
      //示例如下:
      var x = 0;
      function test() { console.log(this.x); }
      var obj = {};
      obj.x = 1;
      obj.m = test;
    
      //apply无参,则代表指向全局对象
      obj.m.apply()// 0 
    
      //指定绑定this到obj上
      obj.m.apply(obj) //1
    
  • call调用改变this

    用法: call(thisObj, arg1, arg2, arg3, arg4);
    
    //示例代码:
    var name = "Jerry";
    var obj = { name: "Tom" };
    function sayName() {
      return this.name;
    }
    
    console.log(sayName.call(this));//Jerry
    console.log(sayName.call(obj));//Tom
    
    

3、比较typeof 与 instanceof

  • 相同点:JS中 typeofinstanceof 常用来判断一个变量是否为空,或者什么类型的

1)typeof 的用法:

  • 定义和用法:typeof返回值是一个字符串,用来说明变量的数据类型。

      var a = 1;
      typeof a // "number"
    
  • 细节:

    - typeof 一般只能返回:number boolean string function object undefined
    - 对于Array, null 等特殊对象,使用 typeof 一律返回 object,这正是它的局限性。
    
    

2)instanceof的用法:

  • 定义:instanceof用于判断一个变量是否属于某个对象的实例。

      var a = new Array();
      console.log(a instanceof Array); //true
      console.log(a instanceof Object);// true,因为 Array 是 Object 的子类
    
      function test() { }
      var a = new test();
      console.log(a instanceof test); //true
    

4、JS 中面向对象中继承实现

1)使用prototype方式

  //继承方式,原型链形式,将方法挂载在 prototype 对象上
  function teacher(name) { this.name = name; }
  teacher.prototype.sayName = function () { console.log("name is" + this.name) }
  var teacher1 = new teacher("xiaoming");
  teacher1.sayName();

  //子类继承父类
  function student(name) { this.name = name; }
  student.prototype = new teacher();
  var student1 = new student("xiaohong");
  student1.sayName();

2)使用 call() / apply() 方式

  function teacher(name, age) {
    this.name = name;
    this.age = age;
    this.sayHi = function () { console.log('Name:' + name + ", Age:" + age) };
  }

  function student() {
    var args = arguments;
    teacher.call(this, args[0], args[1]);
  }

  var teacher1 = new teacher('xiaoming', 30);
  teacher1.sayHi();

  var student1 = new student('xiaolan', 10);
  student1.sayHi();

3)混合方法(prototype, call / apply

  function teacher(name, age) {
    this.name = name;
    this.age = age;
  }

  teacher.prototype.sayName = function () { onsole.log('name:' + this.name); }
  teacher.prototype.sayAge = function () { console.log('age:' + this.age); }

  function student() {
    var args = arguments;
    teacher.call(this, args[0], args[1]);
  }

  student.prototype = new teacher();
  var student1 = new student('xiaolin', 23);
  student1.sayName();
  student1.sayAge();

5、JS 中的强制类型转换

(1)显式转换

  var a = "42";
  var b = Number( a );
  a; // "42"
  b; // 42 -- 是个数字!

(2)隐式转换

  var a = "42";
  var b = a * 1; // "42" 隐式转型成 42 
  a; // "42"
  b; // 42 -- 是个数字!

6、JS 中的相等性

  • (1)严格比较 (如===)在不允许强制转型的情况下检查两个值是否相等

  • (2)抽象比较 (如==)在允许强制转型的情况下检查两个值是否相等

      var a = "42";
      var b = 42;
      a == b; // true
      a === b; // false
    

7、"use strict"的作用是什么?

说明: use strict出现在JS代码的顶部,可以帮助你写出更安全的JS代码。如果你错误的创建了全局变量,他会抛出错误的方式来警告你

  • 例如:如下代码因为x 没有被定义,并使用了全局作用域中的某个值对其进行赋值,加了 use strict 后就会报错。

      function doSomething(val) {
        "use strict"; 
        x = val + 10;
      }
    
  • 将变量声明到函数内部,严格模式下不会报错,如下:

      function doSomething(val) {
      "use strict"; 
      var x = val + 10;
      }
    

8、null 和 undefined

首先声明: 他们都是JS的两种类型。

  • 尚未初始化:undefined

  • 空值:null

  • 注意:nullundefined 是两个不同的对象,如下:

      null == undefined // true
      null === undefined // false
    

9、delete 操作符

  • 说明:delete 操作符,只适用于删除对象的属性

      var a = {b:1}
      delete a.b;
      console.log(a) //object {}
    
  • 如果想要删除对象:

      a = null;
    
  • delete 删除变量不可行

    var name = 'lily';
    delete name;
    console.log(name); //lily
    
  • delete 删除不了原型链中的变量

    fun.prototype.age = 18;
    delete obj.age;
    console.log(obj.age) //18
    

10、JavaScript 创建对象的几种方法

  • 对象字面量法:

      var obj = {}
    
  • 工厂模式:

    function Person(name, age) {
      var o = new Object();
      o.name = name;
      o.age = age;
      o.say = function () { console.log(name); }
      return o;
    }
    
  • 构造函数法:

      //1 直接new Object 对象
      var obj = new Object();
    
      //构造函数
      function Person(name, age) {
        this.name = name;
        this.age = age;
        this.say = function () { console.log(name); }
      }
      var person = new Person('hello', 18);
    
  • 原型模式:

    //实现方法与属性共享,可以动态添加对象的属性和方法。但是没法创建实例自己的属性和方法,也没办法传递参数
    function Person() {
      Person.prototype.name = 'jerry';
      Person.prototype.say = function () { console.log(this.name) }
      Person.prototype.friends = ['friend1'];
    }
    
    var person = new Person();
    
  • 构造函数和原型结合:

    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    Person.prototype.say = function () { console.log(this.name) }
    
    var person = new Person('hello');
    

二、Web 性能相关

1、前端性能优化的方法

  • (1)减少 http 请求次数:JS、CSS 源码压缩、图片大小控制合适、网页Gzip CDN 托管,data 缓存,图片服务器等。
  • (2)前端JS+数据,减少由HTML标签导致的宽带浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数。
  • (3)用innerHTML代替DOM操作,优化JavaScript性能。
  • (4)当需要设置的样式很多时,设置className 而不是直接操作style。
  • (5)少用全局变量、缓存DOM节点查找结果。减少IO读取操作。
  • (6)避免使用CSS 表达式,又称 动态属性(Dynamic properties)
  • (7)图片预加载,将样式放到顶部,将脚本放在底部,加上时间戳。
  • (8)避免在页面的主体布局中使用table,table要等其中的内容完全下载之后才会显示出来,显示要比 DIV+CSS布局要慢。
  • (9)CSS Sprites:合并 CSS图片,减少请求数的又一个好办法。
  • (10)LazyLoad Images 在页面刚加载的时候可以只加载第一屏,当用户继续往后滚屏的时候才加载后续图片。
  • (11)减少cookie传输,请求带大cookie会严重影响数据传输,对于静态资源如CSS、Script 传输cookie没有意义。

网站优化的思路:

对普通的网站有一个统一的思路,就是尽量向前端优化、减少数据库操作、减少磁盘IO。向前端优化指的是,在不影响功能和体验的情况下,
能在浏览器执行的不要在服务端执行,能在缓存服务器上直接返回的不要到应用服务器,程序能直接取得的结果不要到外部取得,
本机内能取得的数据不要到远程取,内存能取到的不要到磁盘取,缓存中有的不要去数据库查询。
减少数据库操作指减少更新次数、缓存结果减少查询次数、将数据库执行的操作尽可能的让你的程序完成(例如join查询),减少磁盘IO指尽量不使用文件系统作为缓存、减少读写文件次数等。
程序优化永远要优化慢的部分,换语言是无法“优化”的。

2、垃圾回收机制方式及内存管理

  • 1)定义和用法: 垃圾回收机制(GC:Garbage Collection),执行环境负责管理代码执行过程中使用的内存。

  • 2)原理: 垃圾收集器会定期(周期性)找出那些不再继续使用的变量,然后释放其内存,但是这个过程不是实时的,因为开销比较大,所以GC会按固定时间间隔周期执行。

      function fn1() {
        var obj = { name: "jerry", age: 10 };
      }
    
      function fn2() {
        var obj = { name: "jerry", age: 10 };
        return obj;
      }
    
      var a = fn1();// fn1 方法中的局部变量会被GC回收
      var b = fn2();// fn2 中的局部变量不会被GC回收,因为 obj 被挂载在了全局变量上
    
  • 3)垃圾回收策略: 标记清除(较为常用)和引用计数

    • 标记清除:

      定义和用法:当变量进入环境时,将变量标记"进入环境",当变量离开环境时,标记为:"离开环境"。
      某一个时刻,垃圾回收器会过滤掉环境中的变量,以及被环境变量引用的变量,剩下的就是被视为准备回收的变量。
      到目前为止,IE、Firefox、Opera、Chrome、Safari的js实现使用的都是标记清除的垃圾回收策略或类似的策略,只不过垃圾收集的时间间隔互不相同。
      
    • 引用计数:

      定义和用法:引用计数是跟踪记录每个值被引用的次数。
      基本原理:就是变量的引用次数,被引用一次则加1,当这个引用计数为0时,被视为准备回收的对象。
      
  • 4)内存管理

      1、什么时候触发垃圾回收?
    
        垃圾回收器周期性运行,如果分配的内存非常多,那么回收工作也会很艰巨,确定垃圾回收时间间隔就变成了一个值得思考的问题。
        IE6的垃圾回收是根据内存分配量运行的,当环境中的变量,对象,字符串达到一定数量时触发垃圾回收。垃圾回收器一直处于工作状态,严重影响浏览器性能。
        IE7中,垃圾回收器会根据内存分配量与程序占用内存的比例进行动态调整,开始回收工作。
    
      2、合理的GC方案:(1)、遍历所有可访问的对象; (2)、回收已不可访问的对象。
      3、GC缺陷:(1)、停止响应其他操作;
      4、GC优化策略:(1)、分代回收(Generation GC);(2)、增量GC
    

三、Web 安全

必考:什么是跨域? 跨域请求的方法有哪些?

1、什么是跨域?

  • 定义: 由于浏览器同源策略,凡是发送请求的URL 协议域名端口三者之间任意一与前页面地址不同则为跨域。

  • 存在跨域的情况

    - 网络协议不同,如http协议访问https协议
    - 端口不同,如80端口访问8080端口
    - 域名不同,如taobao.com 访问 baidu.com
    - 子域名不同,如 abc.baidu.com 访问 def.baidu.com
    - 域名和域名对应ip,如www.a.com 访问 10.0.0.8
    

2、跨域请求资源的方法

  • (1)proxy代理

    定义和用法:proxy代理用于将请求发送给后台服务器,通过服务器来发送请求,然后将请求结果传回前端。
    实现方法:通过nginx 代理。
    
    注意点:1、如果你代理的是https协议的请求,那么你的proxy首先需要信任该证书(尤其是自定义证书)或者忽略证书检查,否则你的请求无法成功。
    
  • (2)CORS 【Cross-Origin Resource Sharing】

    • 定义和用法:是现代浏览器支持跨域资源请求的一种最常用的方式。

    • 使用方法: 使用方法:一般需要后端人员在处理请求数据的时候,添加允许跨域的相关操作。如下:

      res.writeHead(200, {
          "Content-Type": "text/html; charset=UTF-8",
          "Access-Control-Allow-Origin":'http://localhost',
          'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
          'Access-Control-Allow-Headers': 'X-Requested-With, Content-Type'
      });
      
  • (3)jsonp

    • 定义和用法:通过动态插入一个script标签。浏览器对script的资源引用没有同源限制,同时资源加载到页面后会立即执行。

    • 特点:通过动态创建script来读取他域的动态资源,获取的数据一般为json格式。

        <script>
            function testjsonp(data) {
              console.log(data.name); // 获取返回的结果
            }
        </script>
        <script>
            var _script = document.createElement('script');
            _script.type = "text/javascript";
            _script.src = "http://localhost:8888/jsonp?callback=testjsonp";
            document.head.appendChild(_script);
        </script>
      
    • 缺点:1、这种方式无法发送post请求。2、另外要确定jsonp的请求是否失败并不容易,大多数框架实现都是结合超时时间来判定的。

四、练习题

1、JavaScript 当中,如果检测一个变量时一个String 类型?

  typeof(obj) === "string"
  typeof obj === "string"
  obj.constructor === String

2、请写出3个使用this的典型应用

  • 在HTML 元素事件属性上使用

      <input type="button" onclick="showInfo(this);" value=”点击一下”/>
    
  • 构造函数

      function Animal(name, color) {
        this.name = name;
        this.color = color;
      }
    
  • apply() / call()求数组最值

      var  numbers = [5, 458 , 120 , -215 ]; 
      var  maxInNumbers = Math.max.apply(this, numbers);  
      console.log(maxInNumbers);  // 458
      var maxInNumbers = Math.max.call(this,5, 458 , 120 , -215); 
      console.log(maxInNumbers);  // 458
    

3、请用JS 去除字符串中的空格

  • 方法一:使用replace正则匹配的方法

      去除所有空格: str = str.replace(/\s*/g,"");
      去除两头空格: str = str.replace(/^\s*|\s*$/g,"");
      去除左空格: str = str.replace( /^\s*/, "");
      去除右空格: str = str.replace(/(\s*$)/g, "");
    
  • 方法二:使用str.trim()方法

      var str = "   xiao  ming   "; 
      var str2 = str.trim(); // xiao ming,str.trim() 的局限性,无法去除中间的空格
    

4、如何获取浏览器URL中查询字符串中的参数

  • 思路:使用 window.location.href,通过 split 方法根据 & 进行分割获取。

      function showWindowHref() {
        var sHref = window.location.href;
        var args = sHref.split('?');
        if (args[0] == sHref) { return ""; }
    
        var arr = args[1].split('&');
        var obj = {};
        for (var i = 0; i < arr.length; i++) {
          var arg = arr[i].split('=');
          obj[arg[0]] = arg[1];
        }
        return obj;
      }
      var href = showWindowHref(); // obj
      console.log(href['name']); // xiaoming
    

5、解释事件冒泡以及如何阻止它?

  • 定义:事件冒泡是指嵌套最深的元素触发一个事件,然后这个事件顺着嵌套顺序在父元素上触发。
  • 如何防止:使用 event.cancelBubbleevent.stopPropagation() (低于IE9)

6、如何检查一个数字是否为正数?

  • 思路:对1进行取模,看是否有余数。

      function isInit(num) { return num % 1 === 0; }
    
      console.log(isInit(4));//true
      console.log(isInit(12.2));//false
      console.log(isInit(0.3));//false
    

7、解释JS "undefined" 和 "not defined"之间的区别

  • not defined: 如果你试图使用一个不存在且尚未声明的变量,JS将报错:“Uncaught ReferenceError: xxx is not defined”
  • undefined表示变量未赋值
aaa // Uncaught ReferenceError: aaa is not defined
typeof aaa// "undefined" 
  • 当我们试图访问一个被声明但未被定义的变量时,会出现undefined错误
  var x; // 声明
  typeof x === 'undefined' // true 

8、匿名函数和命名函数有什么区别?

  //(1)赋给变量foo 的匿名函数
  var foo = function () { }
  //(2)赋给变量x 的命名函数
  var x = function bar() { }

9、如何在JS中创建私有变量?

  • 将变量创建成局部变量,就是这个函数被调用,也无法在函数之外访问这个变量

      function func() { var priv = "secret code"; }
      console.log(priv)// 抛异常 Uncaught ReferenceError: priv is not defined
    
  • 要访问私有变量,需要借助闭包函数

      //要想访问这个私有变量,可以通过闭包的方式,将闭包函数返回
      function func() {
        var priv = "secret code";
        return function () { return priv; }
      }
    
      var getPriv = func();
      getPriv();//"secret code"
    

10、以下代码输出什么?

0.1 + 0.2 === 0.3 //false
//结果为false,这是由浮点数内部表示导致的。0.1+0.2并不刚好等于0.3,实际结果为 0.30000000000000004

11、如何向Array 对象添加自定义方法,让下面的代码可以运行?

  var arr = [1, 2, 3, 4, 5];
  var avg = arr.average();
  console.log(avg);

思路: 用原型 prototype,由于JS的每个对象都链接到另一个对象(也就是对象的原型),并继承原型对象的方法,你可以跟踪每个对象的原型链,
直到到达没有原型的null对象,我们需要通过修改Array原型来向全局Array对象添加方法。

  Array.prototype.average = function () {
    //计算sum 的值
    var sum = this.reduce(function (prev, cur) { return prev + cur; });
    //将sum除以元素个数并返回
    return sum / this.length;
  }

  var arr = [1, 2, 3, 4, 5];
  var avg = arr.average();
  console.log(avg);//3

12、什么是window对象?什么是document对象?

window 对象代表浏览器中打开的一个窗口。
document对象代表整个HTML文档。实际上,document对象是window对象的一个属性。

13、AMD(Modules/Asynchronous-Definition) 和 CMD (Common Module Definition)规范区别?

  • 说明: AMDRequireJS 在推广过程中对模块定义的规范化产出。CMDSeaJS 在推广过程中对模块定义的规范化产出。

  • 区别:

    • 对于依赖的模块,AMD 是提前执行,CMD是延迟执行。不过RequireJS2.0 开始,也改成延迟执行。

    • CMD 推崇依赖就近,AMD 推崇依赖强制。

    • AMD 的 API 默认是一个当多个用,CMD 的API 严格区分,推崇职责单一。

        // CMD
        define(function(require, exports, module) {
            var a = require('./a')
            a.doSomething()
            // 此处略去 100 行
            var b = require('./b') // 依赖可以就近书写
            b.doSomething()
        })
        // AMD 默认推荐
        define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
            a.doSomething();
            // 此处略去 100 行
            b.doSomething();
        })
      

14、JS延迟加载方式有哪些?

  • JS 的延迟加载,有助于提高页面的加载速度。
  defer 和 async 动态创建DOM方式(用的最多),按需异步载入JS。
    defer:延迟脚本。立即下载,但延迟执行(延迟到整个页面都接卸完毕后再运行),按照脚本的先后顺序执行。
    async:异步脚本。下载完立即执行,但不能保证按脚本出现的先后顺序执行。

15、下面代码输出什么?

  var y = 1;
  if (function f(){}) {
      y += typeof f;
  }
  console.log(y); // 1undefined

16、写一个 mul 函数,使用方法如下:

console.log(mul(2)(3)(4)); // output : 24 
console.log(mul(4)(3)(4)); // output : 48

答案:

//使用嵌套闭包即可
function mul(x) {
  return function (y) {
    return function (x) {
      return x * y * z;
    }
  }
}

17、JavaScript 怎么清空数组

var arrayList = ['a','b','c','d','e','f'];
//方法1:
arrayList = [];
//方法2:
arrayList.length = 0;
//方法3:
arrayList.splice(0, arrayList.length);

18、怎么判断一个object是否是数组(array)?

  • 方法一:使用 Object.prototype.toString 来判断

      function isArray(obj){
          return Object.prototype.toString.call( obj ) === '[object Array]';
      }
    
  • 方法二:使用原型链

      function isArray(obj){
          return obj.__proto__ === Array.prototype;
      }
    
  • 方法三:利用JQuery

      function isArray(obj){
          return $.isArray(obj)
      }
    

19、下面代码输出什么?

  var output = (function (x) {
    delete x;
    return x;
  })(0)

  console.log(output);//输出是 0。 delete 操作符是将object的属性删去的操作。但是这里的 x 是并不是对象的属性, delete 操作符并不能作用。

20、下面代码输出什么?

var Employee = { company: 'xyz' }

var emp1 = Object.create(Employee);
delete emp1.company;
console.log(emp1.company); // xyz

//原因是 这里的 emp1 通过 prototype 继承了 Employee 的company。emp1 并没有自己的 company属性,此处delete 无效。

21、什么是undefined x 1?

说明:当我们使用delete 删除一个数组中的元素,这个元素的位置就会变成一个占位符,打印出来就是 undefined x 1

var trees = ["redwood","bay","cedar","oak","maple"];
delete trees[3];
console.log(trees); // ["redwood", "bay", "cedar", empty, "maple"]
console.log(trees[3]); //undefined

22、下面代码输出什么?

var trees = ["xyz","xxxx","test","ryan","apple"];
delete trees[3];
  
console.log(trees.length);//5 delete 操作符删完数组元素后,并不影响数组长度

23、下面代码输出什么?

var bar = true;
console.log(bar + 0);//1
console.log(bar + "xyz");//truexyz  
console.log(bar + true);  //2
console.log(bar + false); //1

可以对照如下操作:

Number + Number -> 加法
Boolean + Number -> 加法
Boolean + Boolean -> 加法
Number + String -> 连接
String + Boolean -> 连接
String + String -> 连接

24、下面代码输出什么?

var z = 1, y = z = typeof y;
console.log(y);  

上面代码等价于

var z = 1
z = typeof y;
var y = z;
console.log(y);// undefined

25、下面代码输出什么?

var foo = function bar(){ return 12; };
typeof bar(); //抛异常, Uncaught ReferenceError: bar is not defined

如下修改不会抛异常

var bar = function(){ return 12; };
typeof bar();
//或者
function bar(){ return 12; };
typeof bar();

26、如下两种函数声明有什么区别?

//foo的定义是在运行时,这种声明方式会有变量提升问题
var foo = function(){}

function bar(){}

如下:使用匿名方式声明,定义的变量会导致变量提升,所以上述代码执行顺序如下

// foo bar的定义位置被提升
function bar(){}; 
var foo;

console.log(foo)// undefined

foo = function(){}; 

27、如下代码输出什么?

var salary = "1000$";

(function () {
    console.log("Original salary was " + salary);
    var salary = "5000$";
    console.log("My New Salary " + salary);
})();

// 答案:  
//Original salary was undefined
// My New Salary 5000$

考察变量提升,上述函数中的 console.log("Original salary was " + salary); 这行代码,先使用了 salary 这个变量,函数内部会有变量提升问题,等价于如下:

  var salary ;
  console.log("Original salary was " + salary);

28、如果我使用JS的“关联数组”,我们怎么计算“关联数组”的长度?

var counterArray = {
    A : 3,
    B : 4
};
counterArray["C"] = 1;

//答案:直接计算key 的数量就可以了
Object.keys(counterArray).length // Output 3

29、JavaScript 中有哪些弹出框?

Alert、Confirm 、Prompt

30、Void(0) 怎么用?

Void(0)用于防止页面刷新,并在调用时传递参数“zero”。
Void(0)用于调用另一种方法而不刷新页面。

31、如何创建通用对象?

var I = new object();
posted @ 2021-05-05 10:22  PS-Jerry  阅读(115)  评论(0编辑  收藏  举报