JavaScript知识点全面概括与总结(中)

本文深入探讨了JavaScript中的模块化开发,包括Cookie、AMD、CMD、ES6模块规范以及requireJS的核心原理。介绍了JavaScript的类、DOM操作、事件循环、垃圾回收机制、前端路由、MVVM框架如Vue的实现原理,以及数据绑定和虚拟DOM的优势。此外,还涵盖了安全相关话题,如CSRF、XSS和SQL注入攻击的防范措施。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

61.cookie的理解
  • cookie 是服务器提供的一种用于维护会话状态信息的数据,通过服务器发送到浏览器,浏览器保存在本地,当下一次有同源的请求时,将保存的 cookie 值添加到请求头部,发送给服务端。这可以用来实现记录用户登录状态等功能。cookie 一般可以存储 4k 大小的数据,并且只能够被同源的网页所共享访问。
  • 服务器端可以使用 Set-Cookie 的响应头部来配置 cookie 信息。一条cookie 包括了5个属性值 expires、domain、path、secure、HttpOnly。其中 expires 指定了 cookie 失效的时间,domain 是域名、path是路径,domain 和 path 一起限制了 cookie 能够被哪些 url 访问。secure 规定了 cookie 只能在确保安全的情况下传输,HttpOnly 规定了这个 cookie 只能被服务器访问,不能使用 js 脚本访问。
  • 在发生 xhr(即XMLHttpRequest) 的跨域请求的时候,即使是同源下的 cookie,也不会被自动添加到请求头部,除非显示地规定。
62.模块化开发的理解
  • 一个模块是实现一个特定功能的一组方法。在最开始的时候,js 只实现一些简单的功能,所以并没有模块的概念,但随着程序越来越复杂,代码的模块化开发变得越来越重要。
  • 由于函数具有独立作用域的特点,最原始的写法是使用函数来作为模块,几个函数作为一个模块,但是这种方式容易造成全局变量的污染,并且模块间没有联系。
  • 后面提出了对象写法,通过将函数作为一个对象的方法来实现,这样解决了直接使用函数作为模块的一些缺点,但是这种办法会暴露所有的所有的模块成员,外部代码可以修改内部属性的值。
  • 现在最常用的是立即执行函数的写法,通过利用闭包来实现模块私有作用域的建立,同时不会对全局作用域造成污染。
63.javascript 的几种模块规范
  • javascript 中现在比较成熟的有四种模块加载方案:
    • 第一种是 CommonJS 方案,它通过 require 来引入模块,通过 module.exports 定义模块的输出接口。这种模块加载方案是服务器端的解决方案,它是以同步的方式来引入模块的,因为在服务端文件都存储在本地磁盘,所以读取非常快,所以以同步的方式加载没有问题。但如果是在浏览器端,由于模块的加载是使用网络请求,因此使用异步加载的方式更加合适。
    • 第二种是 AMD 方案,这种方案采用异步加载的方式来加载模块,模块的加载不影响后面语句的执行,所有依赖这个模块的语句都定义在一个回调函数里,等到加载完成后再执行回调函数。require.js 实现了 AMD 规范。
    • 第三种是 CMD 方案,这种方案和 AMD 方案都是为了解决异步模块加载的问题,sea.js 实现了 CMD 规范。它和 require.js的区别在于模块定义时对依赖的处理不同和对依赖模块的执行时机的处理不同。
    • 第四种方案是 ES6 提出的方案,使用 import 和 export 的形式来导入导出模块。这种方案和上面三种方案都不同。
64.AMD 和 CMD 规范的区别
  • 它们之间的主要区别有两个方面:
    • 第一个方面是在模块定义时对依赖的处理不同。AMD 推崇依赖前置,在定义模块的时候就要声明其依赖的模块。而 CMD 推崇 就近依赖,只有在用到某个模块的时候再去 require。
    • 第二个方面是对依赖模块的执行时机处理不同。首先 AMD 和 CMD 对于模块的加载方式都是异步加载,不过它们的区别在于 模块的执行时机,AMD 在依赖模块加载完成后就直接执行依赖模块,依赖模块的执行顺序和我们书写的顺序不一定一致。而 CMD 在依赖模块加载完成后并不执行,只是下载而已,等到所有的依赖模块都加载好后,进入回调函数逻辑,遇到 require 语句 的时候才执行对应的模块,这样模块的执行顺序就和我们书写的顺序保持一致了。
    // 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();
      // ...
    });
    
65. ES6 模块与 CommonJS 模块、AMD、CMD 的差异
  • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。ES6 模块的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令 import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。CommonJS 模块就是对象,即在输入时是先加载整个模块,生成一个对象,然后再从这个对象上面读取方法,这种加载称为“运行时加载”。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
66.requireJS 的核心原理(动态加载,避免多次加载,缓存)
  • require.js 的核心原理是通过动态创建 script 脚本来异步引入模块,然后对每个脚本的 load 事件进行监听,如果每个脚本都加载完成了,再调用回调函数。
67.造一个javascript 模块加载器的轮子即实现一个模块加载器
  • 在javascript中实现模块系统,同其它语言里一样把一个模块放入一个文件而这个文件最终被当做代码运行,实现这个文件为外界提供内容的主要方式有:
    • 让这个文件里的代码在一个函数内运行,然后返回想要提供给外界的接口。
    • 让这个文件去修改由外部提供给它的一个对象以藉由这个对象来给外界提供接口。
  • 几大模块系统(Node的CommonJS,requirejs的AMD,seajs的CMD)都选择了第二种方式,即让模块代码去修改一个已存在的对象,不过seajs也支持通过模块的代码返回一个对象来导出模块。
    function require(path) {
         
      if (require.cache[path]) {
         
        return require.cache[path].exports
      }
      var src = fs.readFileSync(path)
      var code = new Function('exports, module', src)
      var module = {
         exports:{
         }}
      code(module.exports, module)
      require.cache[path] = module
      return module.exports
    }
    require.cache = Object.create(null)
    
    • 上面代码的意义很明显,把模块对应的文件读出来,通过文件的内容动态构建一个函数,构建出来的这个函数是有两个参数的(上面几个模块系统的实现实际上把require函数也做为参数传进去了),一个名为exports,一个名为module,而且exports是module对象的一个属性,它本身也是个空对象。
    • 然后将exports与module做为参数调用刚刚通过模块文件的内容构建出来的函数,在模块内部,实际上就是在修改exports对象或者是module.exports对象(如果你用过任意一个模块系统这应该是很熟悉的)这个函数运行完成后,module这个对象应该就已经被修改为想要的样子了,把得到的内容缓存以便下次直接返回,同时本次也返回得到的module就完事了。
    • 至于文件的内容是同步获取还是异步获取,那就得看具体环境和需求了,不是模块加载器的原理,requires跟seajs都在浏览器端运行,当然只能选择异步加载了,但seajs的用法看起来地像是同步的,实现方式是加载完后不运行而是分析它的依赖然后递归加载它的依赖,直到所有的依赖都加载完成。
68.ECMAScript6 写 class以及对class 的理解
  • ES6 新添加的 class 只是为了补充 js 中缺少的一些面向对象语言的特性,但本质上来说它只是一种语法糖,不是一个新的东西,其背后还是原型继承的思想。通过加入 class 可以有利于我们更好的组织代码。
  • 在 class 中添加的方法,其实是添加在类的原型上的。
69.documen.write 和 innerHTML 的区别
  • document.write 的内容会代替整个文档内容,会重写整个页面。
  • innerHTML 的内容只是替代指定元素的内容,只会重写页面中的部分内容。
70.DOM 操作——添加、移除、移动、复制、创建和查找节点
  • 创建新节点
    createDocumentFragment(node);
    createElement(node);
    createTextNode(text);
    
  • 添加、移除、替换、插入
    appendChild(node)
    removeChild(node)
    replaceChild(new,old)
    insertBefore(new,old)
    
  • 查找
    getElementById();
    getElementsByName();
    getElementsByTagName();
    getElementsByClassName();
    querySelector();
    querySelectorAll();
    
  • 属性操作
    getAttribute(key);
    setAttribute(key, value);
    hasAttribute(key);
    removeAttribute(key);
    
71.innerHTML 与 outerHTML 的区别
对于这样一个 HTML 元素:<div>content<br/></div>。

innerHTML:内部 HTML,content<br/>;
outerHTML:外部 HTMLÿ
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值