【JavaScript必知】数据类型

仅为学习笔记

JavaScript 中的数据类型

  • 基本类型(6): nullundefinedbooleannumberstringsymbol(es6)。
  • 对象类型(1):Object

区别:

  • 基本类型存储的都是值,对象类型存储的是指针(内存地址)
var a = 1;   分配一块内存#001,存放值为1,a存放值1
var b = a;   分配一块内存#002,存放值为1,b存放值1
console.log(a);   1
console.log(b);   1
两个值互不影响

var a = [];    分配一块内存#001,存放值为[], a存放地址#001
var b = a;     将地址#001赋值给b,此时b的地址也是#001,a和b表明同一个地址
a.push(1)
console.log(a);   [1]
console.log(b);   [1]

同一个地址表明同一个地方,因此会互相影响

复制代码
  • 对象做为函数参数时,参数是按值传递的,对象传递的是地址,因此存在引用。
function test(person) {
  person.age = 26 // 这里参数传入的是对象的地址
  person = {    // 这里从新赋值了,至关于从新分配了地址
    name: 'yyy',
    age: 30
  }
  return person
}
const p1 = {
  name: 'yck',
  age: 25
}
const p2 = test(p1)
console.log(p1) // -> {name: 'yck', age: 25 }
console.log(p2) // -> {name: 'yyy', age: 30 }
复制代码

检测数据类型 typeof

typeof 对于基本类型,除了 null 均可以显示正确的类型,对于对象没法区分是哪种es6

typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof b // b 没有声明,可是还会显示 undefined
复制代码
typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'
复制代码

对于 null 来讲,虽然它是基本类型,可是会显示 object算法

typeof null // 'object'
复制代码

使用 instanceof区分对象

instanceof是经过原型链来判断json

const Person = function() {}
const p1 = new Person()
p1 instanceof Person // true

var str = 'hello world'
str instanceof String // false

var str1 = new String('hello world')
str1 instanceof String // true

复制代码

Number 类型:

JS不存在整型,所有按照 IEEE 754 双精度版本(64位)来表示数字 而计算机计算是采用二进制,因此会将十进制先转成2进制计算后再转成十进制,所以计算有时会出现偏差,好比:0.2 + 0.1 = 0.30000000000000004数组

NaN 非数值的类型, 不等于本身 ,自己是一个Number类型

console.log(NaN == NAN);//false
console.log(typeof NaN); //'number'
复制代码

isNaN():接受任意参数,试图转换为数值,不能被转换的返回true.

console.log( isNaN(NaN) ); //true
console.log( isNaN(10) ); //false
console.log( isNaN(true) ); //false
复制代码

类型转换

在 JS 中类型转换只有三种状况,分别是:bash

  • 转换为Boolean
  • 转换为数字
  • 转换为字符串

转Boolean

在条件判断时,undefined, null, false, NaN, '', 0, -0,转为 false,其余全部值都转为 true。闭包

对象转原始类型

对象在转换类型的时候,会调用内置的 [[ToPrimitive]] 函数,对于该函数来讲,算法逻辑通常来讲以下:app

若是已是原始类型了,那就不须要转换了函数

  • 调用 x.valueOf(),若是转换为基础类型,就返回转换的值
  • 调用 x.toString(),若是转换为基础类型,就返回转换的值 若是都没有返回原始类型,就会报错 固然你也能够重写 Symbol.toPrimitive ,该方法在转原始类型时调用优先级最高。
let a = {
  valueOf() {
    return 0
  },
  toString() {
    return '1'
  },
  [Symbol.toPrimitive]() {
    return 2
  }
}
1 + a // => 3

复制代码

转换成数值:Number,parseInt, parseFloat

Number():字符串--整数 (能够用于任何类型总体转换)
Number(true)--1
Number(false)-0
Number(null)--0
Number([ ])---0  
Number(' ')---0
Number([ 12])---12
Number('100')--100
Number('01000')---1000
转不了的就返回NaN
Number('hello world')----NaN
Number(undefined)----NaN
Number([ 1,2,3])---NaN
Number(json)---NaN  json转不了
Number(function(){} ...window等)---NaN
不能转换含有非数字的东西:Number(100px)--NaN
因为Number()函数在转换字符串比较复杂且不够合理,所以处理整数通常用parseInt()
复制代码

parseInt() parseFloat (只针对字符串) parseInt(一个一个的转换,若是第一个不是数字就转成NaN,只能转字符串类型,) parseInt(字符串,几进制(默认10进制))学习

parseInt(100px)---100
parseInt(10px23)--10
parseInt(+100px)--100(忽略+,-,空格,0000)
parseInt(0100)---100
parseInt(12.2元)--12
parseInt('')--NaN
parseFloat(只认识第1个小数点)
parseFloat(12.32元)--12.32
parseFloat(12.3.2元)--12.3
if(parseInt(num)==parseFloat(num))  说明num是整数
复制代码

四则运算符

加法运算符

  • 其中一方为字符串,那么就会把另外一方也转换为字符串
  • 若是一方不是字符串或者数字,那么会将它转换为数字或者字符串
1 + '1' // '11'
true + true // 2
4 + [1,2,3] // "41,2,3"
复制代码

另外对于加法还须要注意这个表达式 'a' + + 'b'ui

'a' + + 'b' // -> "aNaN"
复制代码

由于 + 'b' 等于 NaN,因此结果为 "aNaN",你可能也会在一些代码中看到过 + '1' 的形式来快速获取 number 类型。

那么对于除了加法的运算符来讲,只要其中一方是数字,那么另外一方就会被转为数字

4 * '3' // 12
4 * [] // 0
4 * [1, 2] // NaN

复制代码

比较运算符

若是是对象,就经过 toPrimitive 转换对象 若是是字符串,就经过 unicode 字符索引来比较

let a = {
  valueOf() {
    return 0
  },
  toString() {
    return '1'
  }
}
a > -1 // true

复制代码

在以上代码中,由于 a 是对象,因此会经过 valueOf 转换为原始类型再比较值。

内置对象 Object Array Boolean Number String Funtion RegExp Error Math

Array

push():在末尾添加1项,并返回新数组的长度
pop(); 从末尾删除1项,并返回删除的那一项
shift(); 从前面删除1项,并返回删除的那一项
unshift(); 从前面增长1项,并返回新数组的长度
复制代码

排序

  • reverse():翻转数组项的顺序
  • sort():调用数组的toString()方法,把每一个数组转成字符串,而后两两想减,负数顺序不变,正数交换位置,实现了从小到大排序,升序排序。由于是比较的字符串,因此没法获得排好顺序的整数。若是要实现整数排序,能够另外写一个函数,利用返回值。
function compare(v1,v2){
  return v2-v1;
}
var value = [1,3,4,0,2];
value.sort(compare)
复制代码

操做

  • join() 数组--字符串
  • concat():它会复制当前数组并把传入的参数加在后面,生成一个新的数组。不会改变原数组。
  • slice():返回一个数组,两个参数:起始和结束位置,不包括结束项。没有结束项,就到最后,不改变数组自己。
  • [].slice.call(arguments)==Array.slice.call(arguments),目的是将arguments对象的数组提出来转化为数组,arguments自己并非数组不能调用slice() ,因此能够经过call转成数组
  • splice():会改变数组 两个参数,splice(要删除的第一项的位置,要删除的个数) 3个参数:起始位置,要删除的个数,要插入的项(能够多个),会从设置的起始位置开始插入
  • indexOf()(从前日后找)和lastIndexOf()(从末尾开始找)查找,找到返回位置,没找到返回-1. 参数:(要查找的项,查找的起始位置。(可选) )
var num = [1,2,3,4,5];
num.indexOf(4); //3
num.lastIndexOf(4); //1
复制代码

迭代方法:参数:(运行的函数,做用域(可选))

  • every():对数组的每一项运行给定的函数,若每一项都返回ture,则最终返回true
  • filter():对数组的每一项运行给定的函数,,则最终返回true的项的数组。
  • forEach():对数组的每一项运行给定的函数,无返回值;
  • map():对数组的每一项运行给定的函数,以数组的形式返回全部项的返回值。
  • some():对数组的每一项运行给定的函数,如有一项都返回ture,则最终返回true.

缩小方法:

  • reduce():从前到后遍历
  • reduceRight():与上面相反 参数:前一个值,当前值,索引,数组 上一次运行的返回值,会做为第一个参数传进去,也就是前一个值
var num = [1,2,3,4,5];
var result = num.reduce (function(prev,cur,index,array){return prev+cur;} );  返回的是每项执行结果
alert(result);//15
复制代码

String

length:长度
var str = 'hello ';
console.log(str.charAt(0)); // h  返回单个字符
console.log(str.charCodeAt(1));  //101  返回字符编码
console.log(str[0]);   //h  可直接经过下标
console.log(str.concat('liujingyi'));//hello liujingyi
console.log(str.concat('liu',' jing'));//hello liu jing
console.log(str+'ljy'); //hello ljy
复制代码
var str = 'abjcdefj';
console.log(str.slice(2));      //jcdefj' 开始位置,结束位置 第二个参数默认到最后 console.log(str.substring(2)); //jcdefj'  开始位置,结束位置   第二个参数默认到最后
console.log(str.substr(2));     //jcdefj' 开始位置,返回的字符个数 第二个参数默认到最后 console.log(str.slice(2,5)); //jcd console.log(str.substring(2,5));//jcd console.log(str.substr(2,5)); //jcdef 复制代码
  • indexOf()(从前日后找)和lastIndexOf()(从末尾开始找)查找,找到返回位置,没找到返回-1. 参数:(要查找的项,查找的起始位置。(可选) )
  • trim():删除先后空格
  • toUpperCase() :转成大写
  • toLowerCase() :转成小写
  • toLocaleUpperCase():针对特定地区,转大写、
  • toLocaleLowerCase():同上,转小写
  • match():参数1个:字符串或者正则, match()方法就是用来检索一个字符串是否存在。若是存在的话,返回要检索的字符串;若是不存在的话,返回null 。
var text = "cat,bat,sat,fat";
var result1 = text.match('at');
var result2 = text.match(/at/);
console.log(result1); //["at", index: 1, input: "cat,bat,sat,fat"]
console.log(result2); //["at", index: 1, input: "cat,bat,sat,fat"]
复制代码
  • search():参数1个:字符串或者正则,用于检索字符串中指定的子字符串,返回的是子字符串的起始位置,若是没有找到任何匹配的子串,则返回-1。
var text = "cat,bat,sat,fat";
var result1 = text.search('at');
var result2 = text.search(/at/);
alert(result1); //1
alert(result2); //1
复制代码
  • replace():参数2个:1 正则或字符串(被替换的) 2 函数或字符串(替换后的) 若是第一个参数是字符串,那么只有字符串的第一个子字符串会被替换,想要所有替换,第一个参数用正则
var text = "cat,bat,sat,fat";
var result = text.replace("at","ond");
alert(result); //"cond,bat,sat,fat"
var text = "cat,bat,sat,fat";
var result = text.replace(/at/g,"ond");
alert(result); //"cond,bond,sond,fond"
复制代码
  • split():分割字符串,以数组形式返回。参数2个:1 分割符,字符串或正则 2 数组的大小
var text = "cat,red,dog";
var result1 = text.split(',');// ["cat", "red", "dog"]
var result2 = text.split(); // ["cat,red,dog"]
var result3 = text.split(',',2); //  ["cat", "red"]
复制代码
  • localeCompare():比较字符串在字母表的顺序,相等返回0,若是传入的字符串在前面就返回1,反之返回-1.
var text = "dog";
var result1 = text.localeCompare('dog');//0
var result2 = text.localeCompare('cat'); // 1
fromCharCode():传入编码,返回字符串
var result1 = String.fromCharCode(104,101,108,108,111); //hello
substr 参数:截取的起始位置 和长度(若是省略截取到最后)
var str="Hello world!";
var n=str.substr(2,3)
n 输出结果:
llo
复制代码
  • substring() 方法返回的子串包括 开始 处的字符,但不包括 结束 处的字符。 参数:开始和结束的位置 在本例中,咱们将使用 substring() 从字符串中提取一些字符::
<script>

var str="Hello world!";
document.write(str.substring(3)+"<br>");
document.write(str.substring(3,7));

</script>
以上代码输出结果:
lo world!
lo w
复制代码

Date对象

var date = new Date();
var year = date.getFullYear();
var month = end(date.getMonth()+1);
var dates = end(date.getDate());
var hours = end(date.getHours()+1);
var minutes = end(date.getMinutes()+1);
var seconds = end(date.getSeconds()+1);
var dayList=['星期日','星期一','星期三','星期四','星期五','星期六'];
var day = dayList[date.getDay()];

var time = year+':'+month+':'+dates+':'+hours+':'+minutes+':'+seconds+':'+day;
console.log(time);
function end(time){
  return time<10?'0'+time:time;
}
复制代码
  • eval():能够执行字符串形式的JS代码 eval("alert(1)");等同与 alert(1);

this指向

  • 当函数做为对象的方法被调用时,this 指向该对象
  • 当函数做为普通函数调用,this 指向 window
  • 构造器调用,当用 new 运算符调用函数时,默认状况下,this表明构造函数返回的对象。
  • 当函数嵌套函数时,子函数中的this会指向window对象,若是子函数是箭头函数则不会改变this的指向。
  • call,apply能够动态地改变传入函数的 this

原型

  • 每一个函数都有一个 prototype 属性,存放constructor(建立该函数的构造函数) 和 __proto__

  • 每一个对象都有__proto__ 属性,指向了建立该对象的构造函数的原型。其实这个属性指向了 [[prototype]],可是 [[prototype]] 是内部属性,咱们并不能访问到,因此使用 _proto_来访问。

  • 对象能够经过 __proto__来寻找上一层的属性,__proto__ 将对象链接起来组成了原型链。

function Fun() {
}
Fun.prototype = {
   constructor: f Func(),
    __proto__: Object
}
Object.prototype = {
   constructor: f Object()
}

var a = new Func()
a.__proto__ 指向Fun.prototype
Fun.prototype.__proto__指向Object.prototype
复制代码

new

  • 新生成了一个对象
  • 连接到原型
  • 绑定 this
  • 返回新对象
  • 在调用 new 的过程当中会发生以上四件事情,咱们也能够试着来本身实现一个 new
function create() {
    // 建立一个空的对象
    let obj = new Object()
    // 得到构造函数
    let Con = [].shift.call(arguments)
    // 连接到原型
    obj.__proto__ = Con.prototype
    // 绑定 this,执行构造函数
    let result = Con.apply(obj, arguments)
    // 确保 new 出来的是个对象
    return typeof result === 'object' ? result : obj
}
复制代码

闭包

一个函数嵌套另外一个函数的时候,子函数能够访问到外部函数的变量,此时就造成了一个闭包,外部函数的变量不会被销毁。

闭包使用场景:

  • 一列button,点击弹出对应索引的时候:在点击监听事件的外层建立当即执行函数,将索引传进去。
  • 建立私有做用域: 将代码放在当即执行函数中,经过返回另外一个函数暴露可访问的参数,没暴露的外界没法访问。
  • 延续局部变量的寿命
闭包可能带来的问题:

使用闭包的同时比较容易造成循环引用,若是闭包的做用域链中保存着一些 DOM 节点,这时候就有可能形成内存泄露。 若是要解决循环引用带来的内存泄露问题,咱们只须要把循环引用中的变量设为 null便可。

相关文章
相关标签/搜索