0%

学习笔记 2020 11 02

学习笔记 2020-11-02

JavaScript 高级程序设计(第4版) 阅读记录

BOM

window 对象

导航与打开新窗口

window.open() 方法可以用于导航到指定 URL ,也可以用于打开新浏览器窗口。这个方法接收 4 个参数,要加载的 URL 、目标窗口、特性字符串和表示新窗口在浏览器历史记录中是否替代当前加载页面的布尔值。

如果 window.open() 的第二个参数是一个已经存在的窗口或窗格的名字,则会在对应的窗口或窗格中打开 URL 。

  1. 弹出窗口

    如果 window.open() 的第二个参数不是已有窗口,则会打开一个新窗口或标签页。第三个参数,即特性字符串,用于指定新窗口的配置。如果没有传第三个参数,则新窗口会带有所有默认的浏览器特性。如果打开的不是新窗口,则忽略第三个参数。

    特性字符串是一个逗号分隔的设置字符串,用于指定新窗口包含的特性。

    设置 说明
    fullscreen yes | no 表示新窗口是否最大化。仅限 IE 支持。
    height 数值 新窗口高度,不能小于 100 。
    left 数值 新窗口的 x 轴坐标。这个值不能是负值。
    location yes | no 表示是否显示地址栏。不同浏览器的默认值也不一样。在设置为 no 时,地址栏可能隐藏或禁用。
    Menubar yes | no 表示是否显示菜单栏,默认为 no 。
    resizable yes | no 表示是否可以拖动改变新窗口大小,默认为 no 。
    scrollbars yes | no 表示是否可以在内容过长时滚动,默认为 no 。
    status yes | no 表示是否显示状态栏,不同浏览器默认值不同。
    toolbar yes | no 表示是否显示工具栏,默认为 no 。
    top 数值 新窗口的 y 轴坐标,这个值不能是负值。
    width 数值 新窗口的宽度,这个值不能小于 100 。
    window.open("http://www.wrox.com/", 
     "wroxWindow", 
     "height=400,width=400,top=10,left=10,resizable=yes");

    window.open() 方法会返回一个对新建窗口的引用。这个对象与普通 window 对象没有区别,只是为控制新窗口提供了方便。

    可以使用 close() 方法关闭新打开的窗口。但该方法只能用于使用 window.open() 创建的弹出窗口。

    新创建窗口的 window 对象有一个属性 opener ,指向打开它的窗口。窗口不会跟踪记录自己打开的新窗口。

定时器

js 是单线程语言,允许使用定时器指定在某个时间之后或每隔一段时间就执行相应的代码。 setTimeout() 用于指定在一定时间后执行某些代码,而 setInterval() 用于指定每隔一段时间执行某些代码。

定时器会返回一个表示该超时排期的数值 ID 。这个超时 ID 是被排期执行代码的唯一标识符,可用于取消该任务。

所有超时执行的代码都会在全局作用域中的一个匿名函数中运行,因此函数中的 this 在非严格模式下始终指向 window,而在严格模式下是 undefined 。

第二个参数的间隔时间指的是向队列添加新任务前等待的时间,而不在乎何时执行也不在乎执行的时长。

系统对话框
  1. alert()
  2. confirm() 返回值为 true 或 false 。
  3. prompt() 返回值为 用户点击确定 ? 文本框内的值 : null
  4. find() 查找的异步对话框。
  5. print() 打引的异步对话框。

location 对象

location 提供了当前窗口中加载文档的信息以及通常的导航功能。它既是 window 的属性,也是 document 的属性。 location 对象不仅保存着当前加载文档的信息,也保存着把 URL 解析为离散片段后能够通过属性访问的信息。

http://foouser:barpassword@www.wrox.com:80/WileyCDA/?q=javascript#contents 为例。

属性 说明
location.hash #contents URL 散列值( 井号后跟零或多个字符 ),如果没有则为空字符串。
location.host www.wrox.com:80 服务器名及端口号
location.hostname www.wrox.com 服务器名
location.href http://www.wrox.com:80/WileyCDA/?q=javascript#contents 当前加载页面的完整 URL。 location 的 toString() 方法返回这个值。
location.pathname /WileyCDA URL 中的路径和文件名。
location.port 80 请求的端口。如果 URL 中没有端口,则返回空字符串。
location.protocol http: 页面使用的协议。通常是 http:https:
location.search ?q=javascript URL 的查询字符串。这个字符串以问号开头。
location.username foouser 域名前指定的用户名。
location.password barpassword 域名前指定的密码。
location.origin http://www.wrox.com URL 的源地址。只读。
查询字符串
let qs = '?q=javascript&num=10';
let searchParams = new URLSearchParams(qs);
console.log(searchParams.toString()); // " q=javascript&num=10"
searchParams.has('num'); // true
searchParams.get('num'); // 10
searchParams.set('page', '3');
console.log(searchParams.toString()); // " q=javascript&num=10&page=3"
searchParams.delete('q');
console.log(searchParams.toString()); // " num=10&page=3"
for (let param of searchParams) {
  console.log(param);
}
// ["num", "10"]
// ["page", "3"]
操作地址

可以使用 assign() 方法来修改浏览器的地址。

location.assign("http://www.wrox.com");

该操作会在浏览器历史记录中增加一条记录。直接修改 location.href 或是 window.location 设置 URL ,都会调用 assign() 方法。

除了 hash 之外,修改 location 的一个属性,都会导致页面重新加载新 URL 。

location.replace() 方法不会增加历史记录。

location.reload() 方法会重新加载当前显示的页面。给这个方法传入参数 true 可以使得网页重新从服务器加载。

现代 JavaScript 教程

任务

  1. 数组被拷贝了吗?

    下面的代码将会显示什么?

    let fruits = ["Apples", "Pear", "Orange"];
    
    // 在“副本”里 push 了一个新的值
    let shoppingCart = fruits;
    shoppingCart.push("Banana");
    
    // fruits 里面是什么?
    alert( fruits.length ); // ?

    数组的赋值是引用赋值,所以输出是 4 。

  2. 数组操作

    我们试试下面的 5 个数组操作。

    1. 创建一个数组 styles,里面存储有 “Jazz” 和 “Blues”。
    2. 将 “Rock-n-Roll” 从数组末端添加进去。
    3. 用 “Classics” 替换掉数组最中间的元素。查找数组最中间的元素的代码应该适用于任何奇数长度的数组。
    4. 去掉数组的第一个值并显示它。
    5. 在数组前面添加 RapReggae

    过程中的数组:

    Jazz, Blues
    Jazz, Bues, Rock-n-Roll
    Jazz, Classics, Rock-n-Roll
    Classics, Rock-n-Roll
    Rap, Reggae, Classics, Rock-n-Roll。
    let styles = ['Jazz', 'Blues'];
    styles.push('Rock-n-Roll');
    styles[Math.floor((styles.length - 1) / 2)] = 'Classics';
    console.log(styles.shift());
    styles.unshift('Rap', 'Reggae');
  3. 在数组上下文调用

    结果是什么?为什么?

    let arr = ["a", "b"];
    
    arr.push(function() {
      alert( this );
    })
    
    arr[2](); // ?

    数组对象。获取该函数的形式类似于对象的方法引用,然后调用方法。

  4. 输入数字求和

    写出函数 sumInput(),要求如下:

    • 使用 prompt 向用户索要值,并存在数组中。
    • 当用户输入了非数字、空字符串或者点击“取消”按钮的时候,问询结束。
    • 计算并返回数组所有项之和。

    P.S. 0 是有效的数字,不要因为是 0 就停止问询。

    function sumInput() {
      let numbers = [];
      while (true) {
        let value = prompt("A number please?", 0);
        // 应该结束了吗?
        if (value === "" || value === null || !isFinite(value)) break;
        numbers.push(+value);
      }
      let sum = 0;
      for (let number of numbers) {
        sum += number;
      }
      return sum;
    }
    alert( sumInput() );
  5. 最大子数组

    输入是以数字组成的数组,例如 arr = [1, -2, 3, 4, -9, 6].

    任务是:找出所有项的和最大的 arr 数组的连续子数组。

    写出函数 getMaxSubSum(arr),用其找出并返回最大和。

    例如:

    getMaxSubSum([-1, 2, 3, -9]) == 5(高亮项的加和)
    getMaxSubSum([2, -1, 2, 3, -9]) == 6
    getMaxSubSum([-1, 2, 3, -9, 11]) == 11
    getMaxSubSum([-2, -1, 1, 2]) == 3
    getMaxSubSum([100, -9, 2, -3, 5]) == 100
    getMaxSubSum([1, 2, 3]) == 6(所有项的和)

    如果所有项都是负数,那就一个项也不取(子数组是空的),所以返回的是 0:

    getMaxSubSum([-1, -2, -3]) = 0

    请尝试想出一个快速的解决方案:复杂度可以是 O(n2),有能力达到 O(n) 则更好。

    function getMaxSubSum(arr) {
      let len = arr.length;
      let result = 0;
      for (let i = 0; i < len; i++) {
        for (let j = i + 1; j <= len; j++) {
          let tmp = arr.slice(i, j);
          let sum = tmp.reduce((item, prev) => prev + item);
          if (sum > result) result = sum;
        }
      }
      return result;
    }
    function getMaxSubSum(arr) {
      let result = 0;
      let tmp = 0;
      for (let item of arr) {
        tmp += item;
        if (tmp > result) result = tmp;
        if (tmp < 0) tmp = 0;
      }
      return result;
    }