JS常用知识点(一)

1.js数据类型

  基本类型:String、Number、boolean、null、undefined、Symbol

  引用类型:Object

  null和undefined的区别:undefined表示定义但未赋值。null表示定义并赋值,但值为null,可用于对象的初始化或销毁。

  Symbol表示独一无二的值,最大的用法是用来定义对象的唯一属性名,也可使用 Symbol 定义常量,可以保证这一组常量的值都不相等。

2.判断变量的类型

  typeof:返回数据类型的字符串表达(不能区分Object、null和Array,都会返回'Object')。

  instanceof (实例于):不能区分基本类型string和boolean,除非是(使用new方法实例产生,如:var s = new string() )字符串对象和布尔对象。

  constructor :除了undefined和null,其他类型的变量均能使用constructor判断出类型。不过要注意,constructor属性是可以被修改的,会导致检测出的结果不正确。

  Object.prototype.toString.call() : 目前最好用

    首先在Object.prototype.toString方法被调用时,会执行下面的操作步骤:

      1. 获取this对象的[[Class]]属性的值.

      2. 计算出三个字符串"[object ", 第一步的操作结果Result(1), 以及 "]"连接后的新字符串.

      3. 返回第二步的操作结果Result(2).

      [[Class]]是一个内部属性,所有的对象(原生对象和宿主对象)都拥有该属性。

  判断空对象的方法:①将对象转化为字符串,再判断该字符串是否为"{}"。②for in 循环判断。③jquery的isEmptyObject方法。

           ④Object.getOwnPropertyNames()方法,获取到对象中的属性名,存到一个数组中,返回数组对象,我们可以通过判断数组的length来判断此对象是否为空(此方法不兼容ie8)

           ⑤使用ES6的Object.keys()方法,与④方法类似,是ES6的新方法, 返回值也是对象中属性名组成的数组

3.数据类型转换

  全等和相等的区别:

    相等 ==: 先隐式转换类型再比较。

    全等 ===:直接比较,不转换类型,只要是类型不同就不相等,类型相同的看值是否相等。

    Object.is(value1,value2):ES6 提出“Same-value equality”(同值相等)算法,它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。Object.is与“===”不同之处只有两个:一是+0不等于-0,二是NaN等于自身。

  强制转换和隐式转换:

    使用String(),Number(),Boolean()函数强制转换。

    隐式转换:字符串加数字,数字就会转成字符串。数字减字符串,字符串转成数字。如果字符串不是纯数字就会转成NaN。字符串减数字也一样。两个字符串相减也先转成数字。乘,除,大于,小于跟减的转换也是一样。

         == 时候也会进行隐式转换  ①undefined == null。  ②字符串和数字比较时,字符串转数字。  ③数字为布尔比较时,布尔转数字。  ④字符串和布尔比较时,两者转数字。

  基本包装类型:Boolean,Number,String 这三个基本类型都有自己对应的包装对象。包装对象,其实就是对象,有相应的属性和方法。调用方法的过程,是在后台偷偷发生的。

         引用类型和基本包装对象的区别在于:生存期。引用类型所创建的对象,在执行的期间一直在内存中,而基本包装对象只是存在了一瞬间,所以我们无法直接给基本类型添加方法。

4.原型和原型链

  每一个JavaScript对象(除了 null )都具有的一个属性,叫proto,这个属性会指向该对象的原型,也就是该对象构造函数的prototype属性。

  每个原型本质上还是一个对象,它也有自己的原型,这样就形成了原型链。

  

5.闭包

  在JavaScript高级程序设计(第3版)中是这样描述:闭包是指有权访问另一个函数作用域中的变量的函数。

  或简单理解为定义在一个函数内部的函数,内部函数持有外部函数内变量的引用。

  用途:① 封装变量和方法 ② 缓存 ③ 实现类和继承 ④ 匿名自执行函数

  优点:① 希望一个变量长期存储在内存中。② 避免全局变量的污染。③ 私有成员的存在。

  缺点:① 常驻内存,增加内存使用量。② 使用不当会很容易造成内存泄露。

6.call、apply和bind

  call、apply、bind的作用是改变函数运行时this的指向,第一个参数都是this要指向的对象,然后用其他参数来传参。

  区别:

    call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面。

    apply 的所有参数都必须放在一个数组里面传进去。

    bind 除了返回是函数以外,它 的参数和 call 一样。

7.DOM事件流和事件委托

  事件流又称为事件传播,DOM2级事件规定的事件流包括三个阶段:事件捕获阶段(capture phase)、处于目标阶段(target phase)和事件冒泡阶段(bubbling phase)。

  

 

 

 

  你可以选择是在捕获阶段还是冒泡阶段绑定事件处理函数,这是通过addEventListener()方法实现的,如果这个函数的最后一个参数是true,则在捕获阶段绑定函数,反之false(默认),在冒泡阶段绑定函数。

  在整个事件流的任何位置通过调用事件的 stopPropagation() 方法可以停止事件的传播过程。

 

  事件委托顾名思义:将事件委托给另外的元素。其实就是利用DOM的事件冒泡原理,将事件绑定到目标元素的父节点。

  如果要为大量的元素节点绑定事件,完美可以用事件委托完美解决,直接将事件绑定在这些元素的父节点上,只需要绑定一次,就可以在所有子节点触发事件。

  最适合使用事件委托技术的事件包括click、mousedown、mouseup、keydown、keyup和keypress。

  事件委托的好处: ① 提高JavaScript性能。事件委托可以显著的提高事件的处理速度,减少内存的占用。② 动态的添加DOM元素,不需要因为元素的改动而修改事件绑定。

8.Cookie和Storage

  Cookie: ① 是设计用来在服务端和客户端进行信息传递的。

       ②cookie是以小的文本文件(<4k)形式(即纯文本),完全存在于客户端;cookie保存了登录的凭证,有了它,只需要在下次请求时带着cookie发送,就不必再重新输入用户名、密码等重新登录了。

  Cookie的HttpOnly限制js通过document.cookie来访问Cookie,从而防止XSS(Cross-Site Scripting)攻击。  

  在RFC2109中定义的SET-COOKIE响应报头的格式为:Set-Cookie: Name = Value; Comment = value; Domain = value; Max-Age = value; Path = Value;Secure; Version = 1 * DIGIT;

 

  Storage即浏览器本地储存(5M或更大),在较高版本的浏览器中,js提供了两种存储方式:sessionStorage和globalStorage。在H5中,用localStorage取代了globalStorage。

  sessionStorage用于本地存储一个会话中的数据,这些数据只有在同一个会话中的页面才能访问,并且当会话结束后,数据也随之销毁。所以sessionStorage仅仅是会话级别的存储,而不是一种持久化的本地存储。

  localStorage是持久化的本地存储,除非是通过js删除,或者清除浏览器缓存,否则数据是永远不会过期的。

  浏览器的支持情况:IE7及以下版本不支持web storage,其他都支持。不过在IE5、IE6、IE7中有个userData,其实也是用于本地存储。这个持久化数据放在缓存中,只有不清理缓存,就会一直存在。

 

  Cookie和Storage的区别:

    (1) web storages和cookie的作用不同,web storage是用于本地大容量存储数据(web storage的存储量大到5MB);而cookie是用于客户端和服务端间的信息传递;

    (2) web storage有setItem、getItem、removeItem、clear等方法,cookie需要我们自己来封装setCookie、getCookie、removeCookie

9.数组和对象常见的方法

  数组常用方法:

    1. join (原数组不受影响)

    该方法可以将数组里的元素,通过指定的分隔符,以字符串的形式连接起来。  

    返回值:返回一个新的字符串

    2. split (原数组不受影响)

    该方法是用过指定的分隔符,将字符串分割成数组。

    返回值:返回一个新的数组

   数组的增删操作(直接改变原数组):

    3. push

    该方法可以在数组的最后面,添加一个或者多个元素。

    返回值:返回的是添加元素后数组的长度。

    4. pop

    该方法可以在数组的最后面,删除一个元素。

    返回值:返回的是刚才删除的元素。

    5. unshift
    该方法可以在数组的最前面,添加一个或者几个元素。

    返回值: 返回的是添加元素后数组的长度

    6. shift

    该方法可以在数组的最前面,删除一个元素。

    返回值: 返回的是刚才删除的元素。

   数组的翻转和排序(改变数组)

    7. reverse

    翻转数组

    8. sort

    该方法可以对数组进行排序.

   数组的拼接与截取(原数组不受影响)

    9. concat

    该方法可以把两个数组里的元素拼接成一个新的数组

    返回值: 返回拼接后的新数组 

1 // concat与push的区别
2 let arr1 = [1,2,3];
3 let arr2 = [4,5,6];
4 let arr = arr1.concat(arr2);//arr = [1,2,3,4,5,6];
5 arr1.push(arr2);//arr1 = [1,2,3,[4,5,6]];

    10. slice([start],[end])(左闭右开)

    该方法可以从数组中截取指定的字段,返回出来。

    返回值:返回截取出来的字段,放到新的数组中,不改变原数组。

   删除或增加元素(任意在任何位置,直接改变原数组,没有返回值)

    11. splice(start,count,[element,...])

    从start(从0开始)下标开始,删除count个,并在该位置添加element,start开始全部往后移动。

   查找元素在数组中出现的位置

    12. indexOf

    该方法用来查找元素在数组中第一次出现的位置,无则返回-1。

    结构: arr.indexOf(元素)

    13. lastIndexOf

    该方法用来查找元素最后一次在数组中出现的位置

    ES5新增的遍历数组方法

    1. forEach( function(item,index,arr){} )

    该方法等同于for循环,没有返回值

    2.map( )

    映射,该方法使用和forEach大致相同,但是该方法有返回值,返回一个新数组,新数组的长度和原数组长度相等。

let arr = [1,32,54,6,543];
let res = arr.map(function(item,index,arr){
        //里面的function是一个回调函数,
        //item: 数组中的每一项;
        //index:item 对应的下标索引值
        //arr: 就是调用该方法的数组本身
    return item*2;
})  //res=[2, 64, 108, 12, 1086]  

    3. filter( function(item, index) {return item;} )

    filter方法: 有返回值(过滤后的数组), 过滤出符合条件(回调函数返回值为true)的元素。

    4. some( function(item) { return item.done; } )

    判断数组中有没有符合条件的项(只要有,就返回true),如果一个都没有,才返回false。

    5. every( function(itemreturn item.done} )

    判断数组中所有的项是否满足要求,如果全都满足,才返回true,否则返回false。

 

     6. findfunction(itemreturn item.done} )

    找到符合条件的项,并且返回第一项。

    7. findIndexfunction(itemreturn item.done} )

    到符合条件的项的下标,并且返回第一个。

    8.reducefunction(total,currentValue,[currentIndex],[arr] ){} , [initialValue] 

​       求和计算:

var arr1 = [1,2,3,4,5] ;
var new1 = arr1.reduce(function(pre,next,index){
        return pre+next ;
        //pre+next=10+5=15
})

      扁平化数组(拼接数组):

var arr2 = [[1,2,3],[4,5],[6,7]] ;
var new2 = arr2.reduce(function(pre,next,index){
        return pre.concat(next);    //前数组拼接后数组 .concat()
})

      对象数组叠加计算:

var arr3 = [
    {price:10,count:1},
    {price:15,count:2},
    {price:10,count:3}
];
var new3 = arr3.reduce(function(pre,next,index){
    return pre+next.price*next.count;
},0)    
//在原数组第一项添加为0,不改变原数组,则可不操作第一项

    ES6新增的数组方法

  对象常用方法

    Object.assign(target,...sources)

    用于将所有可枚举属性的值从一个或者多个源对象复制到目标对象,将返回目标对象,参数target是目标对象,参数sources是源对象。

    此方法实现的是深拷贝,但是这种情况只能进行第一层的深拷贝,更深层次的拷贝还是传址的。

 

//第一层为深拷贝    
var obj1 = {
    a: 1,
    b: 2
};
var obj2 = {};
Object.assign(obj2, obj1);
obj2.a = 3;
console.log(obj1, obj2);
//输出结果是: {a:1,b:2} {a:3,b:2}
//第二层为浅拷贝
var obj1 = [{ a: 1, b: 2 }, 2, 3];
var obj2 = [];
Object.assign(obj2, obj1);
obj2[0].a = 3;
console.log(obj1, obj2);
// 输出的结果是:[{ a: 3, b: 2 }, 2, 3] 和 [{ a: 3, b: 2 }, 2, 3]
var obj1 = JSON.parse(JSON.stringify(obj));
//可用此方法实现深拷贝

    Object.entries()

    返回一个给定对象自身课枚举属性的键值对数组,其排列方式与使用for···in循环遍历该对象时返回的顺序一致(区别在于for···in循环枚举原型链中的属性)。

    Objection.is(value1,value2) 

    判断两个值是不是相同的值。两个参数是两个需要比较的值。返回一个布尔值表示是不是相同。

    Object.freeze()

    方法可以冻结一个对象,一个被冻结的对象再也不能被修改,冻结了一个对象则不能向这个对象添加新的属性,不能删除该对象以有属性的可枚举性、可配置性、可写性,

    以及不能修改已有属性的值,此外冻结一个对象后该对象的原型也不能被修改。返回和传入的参数相同的对象。

    prototypeObj.isPrototypeOf()

    用于测试一个对象是不是存在在另一个对象的原型链上。

10.new对象时内部做了什么?

    (1) 创建一个新对象;
    (2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象) ;
    (3) 执行构造函数中的代码(为这个新对象添加属性) ;
    (4) 返回新对象。

var obj  = {}; //创建了一个空对象obj
obj.__proto__ = Base.prototype;
//我们将这个空对象的__proto__成员指向了Base函数对象prototype成员对象
Base.call(obj);//我们将Base函数对象的this指针替换成obj,然后再调用Base函数,于是我们就给obj对象赋值了一个id成员变量,这个成员变量的值是”base”

 

 

 

  

posted @ 2020-07-22 15:47  promission  阅读(429)  评论(0编辑  收藏  举报