分类
ECMAScript 规范规定语言类型有六种 Undefined,Null,Boolean,String,Number,和 Object, ES6 又添加了一种基本类型,叫Symbol。
基本类型:
Undefined、Null、Boolean、String、Number、Symbol 都是基本类型
引用类型:
Object 是引用类型,这包括数组(array)、对象(object)、函数(function)等
他们的划分方式其实是其是否可以表示为固定长度, 比如Undefined,Null,Boolean,String,Number 这些可以有固定长度,因此是基本类型,并且保存到了栈上。 Object 由于不可预知长度,并且可以 mutate,因此算引用类型,会被分配到了另一块区域,我们称之为堆(heap)。
其实类型指的是值的类型,不是变量的类型,这是动态语言和静态语言的差异。 对于静态语言来说,我们可以限定一个变量的类型。但是对于 JS 这种动态类型的语言来说, 我们无法给变量限定类型,变量的类型是可变的。举个例子:
var a = 1;
typeof a; // "number"
a = {};
typeof a; // "object"
数据类型判断
===(绝对等于)
绝对等于也是可以用来判断数据类型的,它和==不同点在于它不会进行数据转换,如果两个数据数据类型都不同,===会先去看它们的数据类型,如果不同,则直接返回false,只有完全相等的两个值才会返回true
typeof(鉴别原始类型)
我们可以用typeof来判断值的类型,一般都会返回正确的所属类型的字符串,注意是小写的字符串,但也有两种类型返回的值有所不同:
1、null 它返回的是”object“
typeof null === "object"; // true
如果你想判断一个值是不是 null 类型,你可以这么判断:
function isNull(any) {
return !any && typeof any === "object"; // 因为typeof为"object"的除了null,就是Object类型的值了,比如数组、对象,但它们即使是{},[],直接判断也是返回true,所以这可以区分null和它们
}
2、还有一个就是函数,它返回”function“
typeof function a() {} === "function"; // true
最后,我们来汇总下typeof对于所有类型的值,各自返回什么:
typeof function(){} // 'function'
typeof 12 // 'number'
typeof "123" // 'string'
typeof null // 'object'
typeof undefined // 'undefined'
typeof [123] // 'object'
typeof {a:1} // 'object'
typeof true // 'boolean'
typeof Symbol("KK") // "symbol"
instanceof(鉴别引用类型)
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上,通常被用来鉴别引用类型数据
语法:
object instanceof constructor
object:某个实例对象 constructor:某个构造函数
用来检测 constructor.prototype 是否存在于参数 object 的原型链上。
例子:
var list =[]; //数组list
var object ={}; // 对象object
function obj (val){ //函数obj
return val
}
console.log(list instanceof Array) //true
console.log(list instanceof Object) //true
console.log(object instanceof Object) //true
console.log(Object instanceof Array) //false
console.log(obj instanceof Function) //true
console.log(obj instanceof Object ) //true
小结:
1、每一种引用类型的对象(数组、对象等)都被正确鉴别为Object的实例
2、如果对象之间存在原型链方式继承关系,比如,对象A继承对象B,那么对象A instanceOf 对象B也会返回true,只要之间存在原型链关联就为true;
Array.isArray(…)
数组这种引用类型,有时在不同页面之间传递时,由于上下文不同,再用instanceof判断其是否是数组类型会出现问题,所以为了保险起见,判断是否是数组类型就用Array.isArray(…)方法,如果是数组,会返回true
Number
基本概念/语法:
JavaScript 不是类型语言。与许多其他编程语言不同,JavaScript 不定义不同类型的数字,比如整数、短、长、浮点等等。
在JavaScript中,数字不分为整数类型和浮点型类型,所有的数字都是由 浮点型类型。JavaScript 采用 IEEE754 标准定义的 64 位浮点格式表示数字
此格式用 64 位存储数值,其中 0 到 51 存储数字(52位),52 到 62 存储指数(11位),63 位存储符号(1位)
最大值(Number.MAX_VALUE):它能表示最大值为 ±1.7976931348623157e+308
最小值(Number.MIN_VALUE):为 ±5e-324。
不同进制表示法:
二进制:用0和1来表示二进制数字,由于计算机只认识二进制,所以所有的代码最终都会转换成二进制数据
八进制:前缀为 0,则 JavaScript 会把数值常量解释为八进制数
十进制:默认情况下JavaScript 数字为十进制显示
十六进制:前缀为0x ,js会解释为十六进制数
5 // 用二进制表示为101
13 // 用八进制表示为015
22 // 用十六进制表示为0x16
10 // 用十六进制表示为0xa
数字中3个特殊的值:
infinity:代表无穷大,大于任何数值
-infinity: 代表负无穷大,小于任何值
NaN:not a number ,表示非数值
String
基本语法:
字符串:用单引号或者双引号包起来的都是字符串
var str1="Volvo XC60";
var str2='Volvo XC60';
你使用位置(索引)可以访问字符串中任何的字符:
var char=str1[7] // C
注意:索引值从0开始
你也可以在字符串中使用引号,只要内部引号和外部包围的引号不一致即可
var answer="It's alright";
var answer="He is called 'Johnny'";
var answer='He is called "Johnny"';
或者在字符串中使用转义字符()使用引号,这样即使和外围引号相同业务关系,因为内部的已经被转义了
var answer='It\'s alright';
var answer="He is called \"Johnny\"";
常用属性:
字符串(String)使用长度属性length来计算字符串的长度:
var txt="Hello World!";
document.write(txt.length); // 12
var txt="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
document.write(txt.length); // 26
常用方法:
indexOf()
该方法可以实现在字符串中查找指定字符串,找到了就会返回字符串所对应的开始索引值,没找到则返回-1
const a ="Click the buttontolocate"
a.indexOf('locate') //18
a.indexOf('haha') // -1
replace()
该方法可以实现在字符串中用某些字符替换另一些字符,如果能找到指定字符,则会被替换掉,如果找不到则还是保持不变
str="Please visit Microsoft!"
var n=str.replace("Microsoft","Runoob"); // "Please visit Runoob!" 正常被替换
var n=str.replace("haha","Runoob"); // "Please visit Microsoft!" /保持原样
toUpperCase() / toLowerCase()
该方法实现字符串大小写转换,返回一个新的字符串,并不会影响原字符串的值
const txt="Hello World!";
console.log(txt.toUpperCase() ) //"HELLO WORLD!"
console.log(txt.toLowerCase() ) //hello world!
console.log(txt) //"Hello World!" //还是原先的值
concat()
该方法用于连接两个或多个字符串。
const str1="Hello "
const str2="world!"
console.log(str1.concat(str2)) //Hello world!
注意:使用 " + " 运算符来进行字符串的连接运算通常会更简便一些。
slice()
slice(start, end) 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。
使用 start(包含) 和 end(不包含) 参数来指定字符串提取的部分。
start 参数字符串中第一个字符位置为 0, 第二个字符位置为 1, 以此类推,如果是负数表示从尾部截取多少个字符串,slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。
end 参数如果为负数,-1 指字符串的最后一个字符的位置,-2 指倒数第二个字符,以此类推。
概括:
1、就是start和end的值,如果是正数,则是看索引值来找的,但如果是负数,则表示从最后开始数第几个,比如start=-2,则表示起始位置是倒数第二个数开始;
2、截取字符串时不包括下标为end的元素
3、end是可选参数,没有时,默认从start到结束的所有字符串
4、当start和end值相等时,则提取的就是一个长度为0的空字符串;
5、如果start值所对应的位置在end值对应位置的后面(右边,则结果会返回一个空字符串,表明slice不能反向截取,start值必须在end值的左边才行
substring()
该方法也是根据指定的start、end索引来截取相应的字符,效果和slice相似
概述:
1、返回的字符串中同样不包括 end处的字符,和slice一样
2、当参数为负数时,直接会将其转为0,这点和slice有点不同
3、如果参数 start 与 end 相等,那么该方法返回的就是一个空串(即长度为 0 的字符串)
4、如果 start 比 end 大,那么该方法在提取子串之前会先交换这两个参数,这点和slice也是不太一样的
split()
split() 方法用于把一个字符串根据指定的分隔符分割成字符串数组。
var str="How are you doing today?";
var n=str.split(" "); //['How', 'are', 'you', 'doing', 'today?']
注意:
1、如果把空字符串 ("") 用作 separator,那么 stringObject 中的每个字符之间都会被分割。
2、split() 方法不改变原始字符串。
Null
Null类型是第二个只有一个值的数据类型,这个特殊的值是null,从逻辑角度来看,null值表示一个空对象指针,而这也正是使用typeof操作符检测null值会返回“object”的原因
实际上,undefined值是派生自null值的,因此ECMA-262规定对他们的相等测试要返回true:
undefined==null // true
判断null值的方法:
- 使用typeof 和!组合判断
function isNull(any) {
return !any && typeof any === "object"; // 因为对象判断是否存在时都会返回true,即使是空对象也是true
}
- 直接用===判断
const a = null;
if(a===null){
console.log(a就是null)
}
Undefined
如果一个变量声明了,但未被赋值,此时它的值就是undefined,他是一个特殊的值,表示这是JavaScript最初设置的值
有些人会认为,undefined和not defined指的是同一件事。其实不是的,
undefined是已经存在的变量,但是没有赋值,Javascript会给这个已经存在的变量一个默认的undefined值
var a;
console.log(a); //undefined
判断一个值是否是undefined,可以有以下两种方法
var a;
a===undefined //true
typeof a === 'undefined' //true
Boolean
该类型只有两个字面值;true和false;
将其他类型转换为布尔类型:
只有0、NaN、’’、null、undefined五个值转换为false,其余都转换为true(而且没有任何的特殊情况)
Boolean(true) // true
Boolean(false) // false
Boolean('Hello Wolrd') // true
Boolean() // false
Boolean('') // false
Boolean(' ') // true (里面有空格)
Boolean(1) // true
Boolean(0) // false
Boolean(NaN) // false
Boolean({}) // true
Boolean([]) // true
Boolean(null) // false
Boolean(undefined) // false
把其他类型转换为布尔类型有三种方式:
- Boolean()
- if(){}中的条件判断
- !和!! 取反运算符
Object
js中Object是什么?
首先我们必须对Object和Object()做区分:
下面的例子中 a是通过new Object()出来的实例对象,a实例对象的原型对象是Object
原型对象所有的属性和方法如下:
Object()其实是一个构造函数,可以理解为是用来创建对象的一个对象包装器,本质上就是原型对象的构造函数,由于所有通过Object()构造函数创建出来的实例对象都会继承原型对象身上的属性和方法,所以所有实例对象的constructor也指向Object()这个构造函数,需要区分下:实例对象上并没有constructor属性,而是继承原型对象来的
Object属性
1、Object.length
Object.length 值为1,该属性基本没有什么用处
2. Object.prototype
可以为所有 Object 类型的对象添加属性。例如我们给所有原型对象加一个console方法
const a =new Object(); //实例对象
const b = new Array(); //数组
const c = function(){ //函数
console.log('我是函数')
}
Object.prototype.sayHello=function(){
console.log('hello')
}
a.sayHello(); //hello
b.sayHello(); //hello
c.sayHello(); //hello
因为所有对象类型都继承于Object,所以都具有sayHello方法
Object常用方法
Object.assign()
定义:通过复制一个或多个对象来创建一个新的对象。方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象
语法:Object.assign(target, …sources)
参数: target目标对象。ources源对象
const c1 ={
name:"c1",
age:11,
}
const c2={
say:function(){console.log("say")}
}
const c3 = {
do:function(){console.log("do")}
}
const c4 = Object.assign(c1,c2,c3);
console.log(c4) //{ name: 'c1', age: 11, say: [Function: say], do: [Function: do] }
console.log(c1) //{ name: 'c1', age: 11, say: [Function: say], do: [Function: do] }
console.log(c1===c4) //true
小结:Object.assign()返回的是目标对象
Object.entries()
方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for…in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)
Object.keys()
返回一个包含所有给定对象自身可枚举属性名称的数组,返回一个所有元素为字符串的数组,其元素来自于从给定的object上面可直接枚举的属性。这些属性的顺序与手动遍历该对象属性时的一致
Symbol
ES6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名
Symbol 函数栈不能用 new 命令,因为 Symbol 是原始数据类型,不是对象。可以接受一个字符串作为参数,为新创建的 Symbol 提供描述,用来显示在控制台或者作为字符串的时候使用,便于区分
let sy = Symbol("hello");
console.log(sy); // Symbol(hello)
typeof(sy); // "symbol"
// 相同参数 Symbol() 返回的值不相等
let sy1 = Symbol("hello");
sy === sy1; // false
既然刚才说了该类型通常被用作对象的属性,那我们就来看看怎么用作对象的属性呢?
//定义一个person对象,原先有两个属性name和age,现给他增加一个symbol类型属性-成绩等级
const sym = Symbol(’成绩等级‘)
const person = {
name:'小明',
age:12,
[sym] :"优秀"
}
console.log(person) //age: 12,name: "小明",Symbol(成绩等级): "优秀"
//我们尝试用for..in来遍历获取下person对象此时的属性
for(let key in person ){
console.log( key ) // 只有name,和age,并没有发现那个新加的Symbol类型属性
}
// 如何获取刚才的新加属性值呢?
console.log(person[sym]) //优秀
注意:Symbol 值作为属性名时,该属性是公有属性不是私有属性,可以在类的外部访问。但是不会出现在 for…in 、 for…of 的循环中,也不会被 Object.keys() 、 Object.getOwnPropertyNames() 返回。如果要读取到一个对象的 Symbol 属性,可以通过 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 取到。
const symList = Object.getOwnPropertySymbols(student) // [Symbol(’成绩等级‘)]
for(let key of symList){ //用for..of遍历得到的symlist数组
console.log(key) //Symbol(成绩等级)
console.log(student[key] ) // 优秀
}