前端刷题总结——JS

178 阅读9分钟
  1. 基本数据类型和引用数据类型

  ECMAScript包括两个不同类型的值:基本数据类型和引用数据类型。

  基本数据类型指的是简单的数据段,引用数据类型指的是有多个值构成的对象。

  当我们把变量赋值给一个变量时,解析器首先要确认的就是这个值是基本类型值还是引用类型值。

(1)常见的基本数据类型:Number、String 、Boolean、Null、Undefined。基本数据类型是按值访问的,因为可以直接操作保存在变量中的实际值。


  var b = a;

  b = 20;

  console.log(a); // 10值

上面,b获取的是a值得一份拷贝,虽然,两个变量的值相等,但是两个变量保存了两个不同的基本数据类型值。b只是保存了a复制的一个副本。所以,b的改变,对a没有影响。

(2)引用类型数据:也就是对象类型Object type,比如:Object 、Array 、Function 、Data等。javascript的引用数据类型是保存在堆内存中的对象。

与其他语言的不同是,你不可以直接访问堆内存空间中的位置和操作堆内存空间。只能操作对象在栈内存中的引用地址。所以,引用类型数据在栈内存中保存的实际上是对象在堆内存中的引用地址。通过这个引用地址可以快速查找到保存中堆内存中的对象。


  var obj2 = obj1;

  obj2.name = "我有名字了";

  console.log(obj1.name); // 我有名字了

两个引用数据类型指向了同一个堆内存对象。obj1赋值给obj2,实际上这个堆内存对象在栈内存的引用地址复制了一份给了obj2,但是实际上他们共同指向了同一个堆内存对象,实际上改变的是堆内存对象。

我们应该明确一点:ECMAScript中所有函数的参数都是按值来传递的。但是为什么涉及到原始类型与引用类型的值时仍然有区别呢?还不就是因为内存分配时的差别。

  1)原始值:只是把变量里的值传递给参数,之后参数和这个变量互不影响。   2)引用值:对象变量它里面的值是这个对象在堆内存中的内存地址,这一点你要时刻铭记在心,因此它传递的值也就是这个内存地址,这也就是为什么函数内部对这个参数的修改会体现在外部的原因了,因为它们都指向同一个对象。

  1. get请求传参长度 误区:我们经常说get请求参数的大小存在限制,而post请求的参数大小是无限制的。 实际上HTTP 协议从未规定 GET/POST 的请求长度限制是多少。对get请求参数的限制是来源与浏览器或web服务器,浏览器或web服务器限制了url的长度。为了明确这个概念,我们必须再次强调下面几点:

HTTP 协议 未规定 GET 和POST的长度限制

GET的最大长度显示是因为 浏览器和 web服务器限制了 URI的长度

不同的浏览器和WEB服务器,限制的最大长度不一样

要支持IE,则最大长度为2083byte,若只支持Chrome,则最大长度 8182byte

  1. get和post请求的区别

(1)http请求

HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。

HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。

序号方法描述
1GET请求指定的页面信息,并返回实体主体。
2HEAD类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
3POST向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。
4PUT从客户端向服务器传送的数据取代指定的文档的内容。
5DELETE请求服务器删除指定的页面。
6CONNECTHTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
7OPTIONS允许客户端查看服务器的性能。
8TRACE回显服务器收到的请求,主要用于测试或诊断。
9PATCH是对 PUT 方法的补充,用来对已知资源进行局部更新 。

(2)区别

1)get请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连,如:

login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD

如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。   post请求是把请求的数据放在请求体中。   但是这种做法也不时绝对的,大部分人的做法也是按照上面的说法来的,但是也可以在get请求加上 request body,给 post请求带上 URL 参数。

2)get请求提交的url中的数据最多只能是1024字节,这个限制是浏览器或者服务器给添加的,http协议并没有对url长度进行限制,目的是为了保证服务器和浏览器能够正常运行,防止有人恶意发送请求。

  post请求则没有大小限制。

3)post请求相对于get请求更安全。

因为get请求传递的参数会显示在url中,用户在访问的时候浏览器会缓存网页,这样别人在查看浏览器浏览记录的时候会获取私人信息,post请求不会被用户看到,所以安全性高。

POST请求传递参数放在Request body中,不会在url中显示,比GET要安全,且参数长度无限制。

4)get方式需要使用Request.QueryString来取得变量的值。而post方式通过Request.Form来获取变量的值。

  Request.QueryString用法:

   如<a href=”4-1.asp?name=白芸&age=22”>

   就可以用request.querystring(“name”)来获得上面链接传来的参数值。

   例:a1=request.querystring("name")  a2=request.querystring("age")

   则 a1为"白芸",a2为"22".

  Request.Form用法:

   在CS文件中获得对应页面中的下拉框DropDownList_sitebranch值可以有以下几种方法获得:

   siteInfo.FZJGID = Request.Form["DropDownList_sitebranch"].ToString();

5)get请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存。

post不同,post做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存。因此get请求适合于请求缓存。

GET请求刷新浏览器或回退时没有影响

POST回退时会重新提交数据请求

  1. 闭包

(1)变量作用域

JavasSript 语言的特别之处就在于:函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。

注意点:在函数内部声明变量的时候,一定要使用 var 命令。如果不用的话,你实际上声明的是一个全局变量!

(2)一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

让外部访问函数内部变量成为可能;

局部变量会常驻在内存中;

可以避免使用全局变量,防止全局变量污染;

会造成内存泄漏(有一块内存空间被长期占用,而不被释放);解决方法是,在退出函数之前,将不使用的局部变量全部删除。

(2)闭包的创建

闭包就是可以创建一个独立的环境,每个闭包里面的环境都是独立的,互不干扰。闭包会发生内存泄漏,每次外部函数执行的时候,外部函数的引用地址不同,都会重新创建一个新的地址。但凡是当前活动对象中有被内部子集引用的数据,那么这个时候,这个数据不删除,保留一根指针给内部活动对象。

闭包内存泄漏为: key = value,key 被删除了 value 常驻内存中; 局部变量闭包升级版(中间引用的变量) => 自由变量;

(3)闭包怎么读取函数内部的局部变量

需要获取到函数内部的局部变量。但是,正常情况下,这是办不到的,只有通过变通的方法才能实现。那就是在函数内部,再定义一个函数。

function f1(){
    var n=999;
    function f2(){
        alert(n); // 999
    }
}

函数 f2 就被包括在函数 f1 内部,这时 f1 内部的所有局部变量,对 f2 都是可见的。但是反过来就不行,f2 内部的局部变量,对 f1 就是不可见的。

这就是 JavasSript 语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

既然 f2 可以读取 f1 中的局部变量,那么只要把 f2 作为返回值,我们不就可以在 f1 外部读取它的内部变量了吗。

(4)闭包的作用

可以读取函数内部的变量,让这些变量的值始终保持在内存中,不会在 f1 调用后被自动清除。

原因就在于 f1 是 f2 的父函数,而 f2 被赋给了一个全局变量,这导致 f2 始终在内存中,而 f2 的存在依赖于 f1,因此 f1 也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

  1. 类的创建和继承