作者 | Jeskson
掘金 | https://juejin.im/user/5a16e1f3f265da43128096cb
2020年01月09日
引用类型的值(对象)是引用类型的一个实例。引用类型有时也称对象定义,因为它们描述的是一类对象所具有的属性和方法。
对象是某个特定引用类型的实例,新对象是使用new操作符后跟一个构造函数来创建的,构造函数本身就是一个函数,只不过该函数是出于创建新对象的目的而定义的。
ver dada = new Object();
JavaScript对象划分为:
引用类型,基本包装类型,内置对象
JavaScript引用类型分:Object类型,Array类型,RegExp类型,Date类型,Function类型。
基本包装类型,Boolean类型,Number类型,String类型。
Object类型
Object类型是JavaScript中常见的一种类型,使用new操作符
vardada =newObject();dada.name ="dada";dada.age =12;
使用对象字面量表示法:
vardada = {name:'dada',age:12,}
访问对象的属性
console.log(dada.name);console.log(dada['name']);
vardadaname ="dada";console.log(dada[dadaname]);
注意,除非是必须非要使用变量来访问属性,否则不建议使用,还是建议使用点方法来表示。
new运算符的作用就是创建一个对象的实例,这个对象可以是用户自定义,也可以是带有构造函数的一些系统自带的对象。
创建Object类型有两种方法:
第一,使用new运算符创建Object,第二,使用对象字面量方式创建Object,使用最多。
判断js对象是否拥有这个属性,第一种,使用in判断对象的所有属性,包含对象实例以及其原型的属性;第二种,使用
Object.hasOwnProperty(proName);判断的是对象的实例是否具有某个属性。
引用类型通常叫做类,即是,遇到引用值,可以理解为对象。
对象是由 new 运算符加上要实例化的对象的名字创建的
varo =newObject();
Object对象具有的属性
constructor对创建对象的函数的引用(指针),对于Object对象,该指针指向原始的Object()函数。
检测数组
instanceof
Array.isArray(value)
Object.prototype.toString.call(obj)
转换方法
toString() 返回字符串
valueOf() 返回数组本身
toLocaleString()
join()
vardada = ['da1','da2'];dada.toString()"da1,da2"dada.valueOf()['da1','da2']
添加移除
push()数组末尾接收任意数量,并返回修改后的数组的长度。
pop()数组末尾移除最后一项,减少length值,返回移除的项
shift()移除数组第一项,并返回该项,数组长度减一
unshift()数组前面添加任意项并返回新的数组的长度
重排序
reverse() 反转
sort()排序
vararr = [1,3,7,9,4,5]vararr2 = arr.sort(function(a,b){// 从小到大的排序returna-b// 从大到小的排序returnb-a})console.log(arr2);
操作方法,concat()创建当前数组的一个副本,如果有参数则添加这个副本的末尾,如果没有参数就返回当前数组的副本。
slice(start,end)接收一个或两个参数,但不返回结束位置的项,不会影响原数组;splice(起始位置,删除的项数量,要插入的项),删除,替换,插入。
dada.splice(1, 0, 'da1','da2');
// dada从1位置插入两项
dada.splice(1,1, 'da1','da2');
// 为在1位置删除1项,插入两项
indexOf()从数组开头向后查找
lastIndexOf()从数组的末尾开始向前查找
返回的是查找项在数组中的位置,如果没有找到就返回-1
基本类型值和引用类型值,基本类型值是简单的数据,而引用类型是指由多个值构成的对象。
基本类型,undefined,null,boolean,number,string
引用类型,Object,Array等
从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份到新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,这个指针指向存储在堆中的一个对象,复制后的结果是,两个变量实际上将引用同一个对象,两个变量对象指向堆内存中同一个Object对象,所以当改变其中一个变量,就会影响另一个变量。
vardada =newObject();vardashu = dada;dada.name='da1';console.log(dashu.name);// da1
数值的传递,函数的参数
在JavaScript中所有函数的参数都是使用值传递的,就是把函数外的值复制传递给函数内部的参数,就好像从一个变量赋值到另一个变量一样
基本类型值的传递如同基类型变量的复制效果一样,引用类型的值传递,就如同引用类型变量的复制一样的效果。
在向参数传递基本类型值时,被传递的值会复制给一个局部变量,在向参数传递引用类型的值时,会把这个值在内存中的地址复制给这个局部变量。
基本类型
functionadd(num){ num =1;returnnum;}varda1 =12;varresult = add(da1);console.log(da1);console.log(result);
引用类型
functionsetName(obj){ obj.name ='dada';}varperson =newObject();setName(person);console.log(person.name);dada
typeof检测基本类型
typeof中 var da; // 检测为undefined
typeof中 var da = null; // 检测为object
typeof中 var da = new Object(); // 检测为object
instanceof检测引用类型的值
如果不是检测的不是引用类型的值,而是基本类型的值,则返回false
如果是引用类型的值,返回为true
vard =newNumber(11);console.log(dinstanceofNumber);true
Object.prototype.toString表示返回一个表示该对象的字符串
Object.prototype.toString.call(null);
"[object Null]"
Object.prototype.toString.call(1111);
"[object Number]"
Object.prototype.toString.call('string');
"[object String]"
总结Object类型,大部分引用类型值都是Object类型的实例,创建Object实例的方式有两种,一种是使用new操作符后跟Object构造函数,一种是使用对象字面量表示法。
array类型,Date类型,RegExp类型,Function类型,基本包装类型是什么呢?
我相信你在学习时一定见到过Array类型,也是最常见的,数组的每一项可以存储任何类型的数据,数组的大小是可以动态变动的,数组的长度越大就可以存储更多的数据。
那么第一问,数组是怎么创建的呢?
数组有哪些自带的属性,如何检查是否为一个数组,数组元素的增删改等,数组与字符串的相互转化,数据的一些方法,如,截取,合并,排序,查找数组元素的元素,如何遍历数组,进行迭代等。
数组的创建,同样数组也有两种基本的创建方式,一种是使用array构造函数,和创建对象一样new Object()方法。看看使用Array构造函数的语句代码:
varda =newArray();newArray();// 创建一个数组newArray([size]);// 创建一个数组并指定长度newArray(element0, element1, ..., elementn);// 创建一个数组并赋值
采用字面量的方法
varda = [];// 创建一个空数组varda1 = [1,2,3];// 创建一个有三个元素的数组
varda1 = [1,2,3];console.log(da1instanceofArray);VM272:1true
vardada = [1,2,3];undefinedconsole.log(Array.isArray(dada));VM422:1true
检查是否是数组的两种方法:
一种使用instanceof,一种使用Array.isArray()方法。
constructor// 返回创建数组对象的原型函数length// 返回数组的长度prototype// 可以增加数组的原型方法和函数
可以看出一个数组中方法:
_proto_concatconstructorcopyWithinentrieseveryfillfilterfindfindIndexflatflatMapforEachincludesindexOfjoinkeyslastIndexOflengthmappoppushreducereduceRightreverseshiftslicesomesortsplicetoLocaleStringtoStringunshift
数组的length属性,返回数组的长度。
vararray =newArray();undefinedconsole.log(array.constructor);VM576:1ƒArray() { [native code] }undefinedconsole.log(array.constructor ===Array);VM615:1trueundefined
constructor属性返回对创建此对象的数组函数的引用,即是返回对象相对应的构造函数。
array.push(元素1,元素2,...)将一个或多个元素添加到数组的末尾,并返回新数组的长度。
array.unshift(元素1,元素2,...)将一个或多个元素添加到数组的开头,并返回新数组的长度。
array.pop()从数组中删除最后一个元素,并返回最后一个元素的值。
原始数组的最后一个元素被删除。
array.shift()删除数组的第一个元素,并返回第一个元素。
原始数组的第一个元素被删除。
array.splice(start 第一个参数为指定开始修改的位置,如果超出了数组的长度就从末尾开始添加内容,如果为负值,就从数组末尾开始的第几位,从1开始计数, deleteCount第二个参数为,要删除的元素的个数,是从start位置开始要删除的元素个数,为0时表示不删除元素,其后的参数为要加入的元素,从start位置开始,添加的元素。
数组转为字符串
array.join('')
所有对象都具有toLocaleString(),toString(),valueOf()方法
varda = [1,23,4];undefinedconsole.log(da.toString());VM727:11,23,4undefinedconsole.log(da.valueOf());VM813:1(3) [1,23,4]undefinedconsole.log(da.toLocaleString());VM861:1undefined
toString()方法(toLocaleStirng方法),返回这个数组中每个值的字符串形式,拼接而成的一个以逗号分隔的字符串,valueOf()方法,返回的是数组本身。
当有一个值为null或者是undefined时,在join()方法,toStirng()方法和valueOf()方法,toLocaleString()方法的返回则都是以空字符串表示。
字符串变化为数组
string.split(第一个参数为字符串或者是正则表达式,从该参数指定的地方对字符串进行分割,第二个参数为指定返回的数组的最大长度)用于把一个字符串分割成字符串数组
数组的截取与合并
array.slice(start,end)方法,从数组中返回start下标开始,直到end下标结束(不包含),该方法不会改变原始数组,只会返回一个新的子数组。
vararr = [2,23,3,23];undefinedarray.slice(-1);[]console.log(arr);VM1019:1(4) [2,23,3,23]undefinedarr.slice(1,3)(2) [23,3]console.log(arr);VM1131:1(4) [2,23,3,23]undefined
可以看出这个方法不会修改原始数组,只是会返回一个新的子数组,如果想要删除数组中的元素,可以使用array.splice()。
数组的合并
array.concat()方法
sort()方法用于对数组的元素进行排序,并返回原数组。
不带参数,按照字符串UniCode码的顺序进行排序。
constarray= ['a','d','c','b'];array.sort();//['a', 'b', 'c', 'd']
按照数值大小进行排序-升序
array.sort((a,b) => {returna-b;// 从小到大排序});
按照数值大小进行排序-降序
array.sort((a,b)=>{returnb-a;// 从大到小排序});
array.reverse()方法
reverse() 方法将数组中元素的位置颠倒,第一个数组元素成为最后一个数组元素,最后一个数组元素成为第一个。
数组的sort()和reverse()方法都对原数组进行了修改,返回值是经过排序之后的数组。
find(callback[, thisArg])方法,用于找出第一个符合条件的数组元素。
[1,3,-5,20].find((n) =>n <0)// -5
findIndex(callback[, thisArg])返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。
[1,3,13,25].findIndex(function(value, index, arr){returnvalue >9;})// 2
functionf(value){returnvalue >this.age;}letperson = {name:'dada',age:20};[1,12,25,5].find(f, person);// 25
includes(第一个参数为要查找的元素,第二个参数为开始查找的索引位置)方法,返回一个布尔值,表示是否存在给定值在该数组中。
array.filter()方法,array.every()方法检测数组中的每个元素是否通过测试的,如果测试通过为true。
arr.some()判断数组汇总是否包含可以通过测试的元素怒,和every不同的是,这里只要某一个元素通过测试,即返回true。
[2,3,15,1,4].some(item=>item >6);// true
leta = [1,2,3,4,5];letb = [];a.forEach((item) =>{ b.push(item 1);});console.log(b);// [2,3,4,5,6]
keys()是对键名的遍历、values()对键值的遍历、entries()是对键值对的遍历。
for(letitemof['a','b'].keys()){ consloe.log(item);//0//1}for(letitemof['a','b'].values()){ consloe.log(item);//'a'//'b'}letarr = [0,1];for(letitemofarr.entries()){console.log(item);// [0, 0]// [1, 1]}
consttotal = [0,1,2,3].reduce((a, b) =>{returna b;},0);// total is 6
constda = [[0,1], [2,3], [4,5]].reduce((a, b) =>{returna.concat(b);}, []);// da is [0, 1, 2, 3, 4, 5]
Array.from()方法可以用来将json数组格式转换为数组
letda = {'0':'a','1':'b','2':'c',length:3};letarr =Array.from(da);// ['a', 'b', 'c']
Array.of()方法可以将一组值转换为数组
letda =Array.of(1,2,3,4);console.log(da);//[1,2,3,4]
console.log(...[1,2,3])// 1 2 3console.log(1, ...[2,3,4],5)// 1 2 3 4 5
栈方法,队列方法
数组的表示像栈一样,栈是一种后进先出的数据结构。
栈中项的插入(叫做推入)和移除(叫做弹出),只发生在一个位置——栈的顶部。
push()方法可以接收任意数量的参数,在数组的末尾逐个添加,并返回修改后数组的长度,pop()方法可以从数组末尾移除最后一项,返回移除的项。
队列方法
队列数据结构的访问方法是先进先出,队列在列表末端添加项,从列表的前端移除项。
every()方法,传入的函数必须对每一项返回true,才会返回true,否则它就返回false,some()方法则是只要传入的函数对数组中的某项返回true,就会返回true。
Object对象具有的属性
constructor
对创建对象的函数的引用(指针),对于Object对象,该指针指向原始的Object()函数。
Prototype
对该对象的对象原型 的引用,对于所有的对象,它默认返回Object对象的一个实例。
方法:
hasOwnProperty(property)
判断对象是否有某个特定的属性,必须要字符串指定该属性
IsPrototypeOf(object)
判断该对象是否为另一个对象的原型
PropertyIsEnumerable
判断给定的属性是否可以用for...in语句进行枚举
toString()返回对象的原始字符串表示。
valuOf()方法返回最合适该对象的原始值。
reduce()方法从数组的第一项开始,逐个遍历到最后。
reduceRight()方法从数组的最后一个项开始,向前遍历到第一项。
JavaScript引用类型中的Date对象
Date 类型使用自 UTC(Coordinated Universal Time,国际协调时间)1970 年 1 月 1 日午夜(零时)开始经过的毫秒数来保存日期。
创建Date对象,使用new 操作符和Date构造函数:
vardate =newDate();vardate =newDate("1178/08/06 04:20:00");vardate =newDate(154656847478617);
静态方法,Date.now()方法返回当前时间距离时间零点,1970年1月1日00:00:00UTC的毫秒数,相当于Unix时间戳乘以1000。
getTime()方法
返回实例距离1970年1月1日00:00:00的毫秒数,等同于valueOf方法
Date类型使用UTC国际协调时间1970年1月1日午夜(零时)开始经过的毫秒数来保存日期。如果调用Date构造函数而不传递参数,则新创建的对象获取的是当前的日期和时间。
如果想要特定的日期和时间创建日期对象,传入参数。
// 提供了两个方法Date.parse()Date.UTC()
Date.parse()方法接收一个表示日期的字符串参数
varnewDate =newDate(Date.parse('May 23, 2010'));
Date.UTC()方法返回表示日期的毫秒数。
getFullYear() 返回四位的年份getMonth() 返回月份(0 ~ 11,0表示1月,11表示12月)getDay() 返回星期几,星期日为0,星期一为1,以此类推getDate() 返回实例对象对应每个月的几号(从1开始)getHours() 返回小时数 (0 ~ 23)getMinutes() 返回分钟数 (0 ~ 59)getSeconds() 返回秒数 (0 ~ 59)getMilliseconds() 返回毫秒数 (0 ~ 999)setTime(milliseconds) 设置毫秒时间戳setYear(year) 设置距离1900年的年数setFullYear(year[, month, date]) 设置四位年份setMonth(month[, date]) 设置月份(0-11)setDate(date) 设置实例对象对应的每个月的几号(1-31),返回改变后毫秒时间戳setHours(hour[, min, sec, ms]) 设置小时(0-23)setMinutes(min[, sec, ms]) 设置分钟(0-59)setSeconds(sec[, ms]) 设置秒(0-59)setMilliseconds() 设置毫秒(0-999)
toDateString()
显示格式星期几,月,日,年
toTimeString()
显示时,分,秒和时区
toLocalDateString()
显示星期几,月,日,和年
toLocaleTimeString()
显示实现的格式显示时,分,秒
toUTCString()
显示完整的UTC日期
RegExp类型
ECMAScript 通过 RegExp 类型来支持正则表达式。
varexpression =/ pattern /flags ;// 模式(pattern)部分可以是任何简单或复杂的正则表达式// 标志(flags)用以标明正则表达式的行为
g表示全局模式,即是模式将被应用于所有字符串
i表示不区分大小写模式
m表示多行模式
RegExp 构造函数接收两个参数:
一个是要匹配的字符串模式,一个是可选的标志字符串。
RegExp实例方法
exec()方法,用于检索字符串的正则表达式的匹配。
string,检索的字符串,返回一个数组,没有则返回null
/d{2,4}/ //匹配2~4个数字
/w{3}d?/ //精确匹配三个单词和一个可选的数字
函数,函数其实是对象,每个函数都是Function类型的实例。
韩式是定义一次就可以调用或者是执行任意多次的一段代码,通过函数可以封装很多代码块,而且可以在任何地方,任何时候调用,函数本身没有运行功能,只有调用才能运行。
函数实际上是对象,每个函数都是Function类型的实例
函数名是指向函数对象的指针,不会与某个函数绑定,使用不带有圆括号的函数名是访问函数指针,不是调用函数。
在函数中,有两个特殊的对象,arguments和this。
functionmethod(){// 没有参数的函数console.log("da");}functionmethod(name){// 带有参数的函数console.log("da1");}
函数声明:
使用函数声明语法
functionmethod(name){returnname;}
使用变量初始化函数
varda =function(name){returnname;}
使用function构造函数
varda1 =newFunction(name);
varadd=newFunction(‘num1’,’num2’,’return num1 num2’);// 不推荐这种方式,因为会导致解析两次代码,// 第一次解析常规ECMAscript代码(全部代码),// 第二次解析传入构造函数中的字符串,从而影响性能。
参数,把函数的返回值作为参数传递,把函数本身作为参数传递。
varresult=add(sum(10),10);varresult=add(sum,10);//sum是一个函数
return返回值,函数也可以不带有返回值,将返回undefined
函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。
定义函数,第一,使用函数声明语法,第二,使用函数吧表达式,第三,使用function构造函数。
函数声明与函数表达式的区别
解释器会先读取函数声明,在使其在执行之前可以访问。
函数声明语法
functionsum(num1, num2){returnnum1 num2;}
使用函数表达式则必须要等到解析器执行到它所在的代码行时,才会执行,变量声明提前,而值留在原地。
console.log(sum(10,10));functionsum(num1, num2){returnnum1 num2;}
在代码执行前,解析器会通过函数声明提升,读取并将函数声明添加到执行环境中,放入到代码树的顶部。
console.log(sum(10,10));// 报错varsum =function(num1, num2){returnnum1 num2;};
此代码函数位于一个初始化语句中,不是函数声明,不会提前,会把var sum提前,也就是在执行到函数所在语句之前,变量sum中不会保存对函数的引用。
函数是对象来着,函数名是指针。函数名仅仅是指向函数的指针,所以,一个函数对象可以有多个名字。
没有重载的概念
functiondada(num){returnnum 100;}functiondada(num){returnnum 200;}varresult = dada(100);//300// 后面的函数覆盖了前面的函数
以上代码实际上与下面的代码没有什么区别:
varda1=function(num){returnnum 100;};da1=function(num){returnnum 200;};varresult = da1(100);//300
函数作为参数传递给另一个函数
要访问函数的指针而不执行函数的话,必须去掉函数名后面的那对圆括号;从一个函数中返回另一个函数。
函数内部的属性
arguments是个类数组对象
传入函数的所有参数,对象有一个叫callee的属性,属性值是一个指针,指向拥有arguments对象的函数本身。
this对象,指向函数执行的环境对象,在哪个对象中执行,就指向哪个对象。
caller属性,保存着调用当前函数的函数的引用
如果是在全局作用域中调用当前函数,它的值为 null。
functionouter(){ inner(); }functioninner(){console.log(inner.caller); } outer();/*输出结果:
ƒunction outer(){
inner();
}
*/
prototype属性:
是一个对象,通过调用构造函数而创建的一个对象,可以由特定类型的所有实例共享的属性和方法。
toString()方法将函数体转换成对应的字符串。
bind()方法:
会创建一个函数的实例,其 this 值会被绑定到传给 bind() 函数的值。
apply()与call()方法
两个方法的作用都是在特定的作用域中调用函数
实际上就是设置函数内部的this值
apply():接收两个参数
一个是函数运行的作用域,
一个是参数数组,可以是数组,也可以是arguments这个类数组对象;
在使用 call()方法时,传递给函数的参数必须逐个列举出来;
区别仅在于接收参数的方式不同。
apply() 和 call() 真正的本质是用来,扩充函数赖以运行的作用域。
基本包装类型
为了便于操作基本数据类型,ECMAScript还提供了3个特殊的引用数据类型:Boolean、Number和String。
引用类型与基本包装类型的区别,在于它们的对象生命周期不同:引用类型:使用new创建引用类型的实例,在执行数据流离开当前作用域时会一直存储在内存中。基本包装类型:自动创建基本包装类型的对象,只执行一行代码的瞬间之后就会立即销毁。这意味着在运行时为基本包装类型值添加属性和方法是无效的。
创建Boolean对象
// 定义了一个名为 da 的布尔对象varda =newBoolean(true);
如果布尔对象无初始值或者其值为:0、-0、null、""、false、undefined、NaN,那么对象的值为false,否则,其值为true
在布尔表达式中,所有的对象都会被转换为true。
引用类型的布尔值,其实是对象,所以在布尔表达式中使用Boolean 对象都会返回为true。
varda =newBoolean(false); alert(typeofda);// object varda1 =false; alert(typeofda1);// boolean
varda =newBoolean(false); alert(dainstanceofBoolean);// true varda1 =false;alert(da1instanceofBoolean);// false
toString()方法
功能:根据布尔值返回字符串 "true" 或"false"。
valueOf()方法
功能:返回 Boolean 对象的原始值,就是返回基本类型值
true 或 false。
创建Number对象
Number类型是数字值创建的引用类型。
varda =newNumber(10);
toFixed()方法
Number类型的toFixed()方法可以接受一个数值,表示保留的小数的个数(会自动四舍五入)。
toString()方法
将Number数值转换为字符串,该方法接受一个可选参数基数,告诉它返回几进制数值的字符串形式,若省略,则默认基数为10,即十进制。
valueOf()方法
valueOf()返回一个 Number 对象的基本数字值。
创建String对象
String类型是字符串值创建的引用类型。
varda =newString("hello world");
charAt()和 charCodeAt()两个方法都接收一个参数
即基于 0 的字符位置
charAt():
以单字符字符串的形式返回给定位置的那个字符
charCodeAt():
返回给定位置的那个字符的字符编码
截取字符串的方法:
slice()、substr()和 substring()
这三个函数,都不改变原本的字符串,只是在原先的字符串上创建了一个副本,返回操作副本后的值。
slice()方法会将传入的负值与字符串的长度相加substr()方法将负的第一个参数加上字符串的长度,而将负的第二个参数转换为0substring()方法会把所有负值参数都转换为0。
indexOf()
方法从索引 0 的位置开始查询子字符串
lastIndexOf()
方法从最后一个索引开始查找字符串
trimLeft()和 trimRight()方法,
分别用于删除字符串开头和末尾的空格。
字符串大小写转换的方法:toLowerCase()、toUpperCase()var stringValue ="hello world"; alert(stringValue.toUpperCase());//"HELLO WORLD"alert(stringValue.toLowerCase());//"hello world"
match()方法
vars ='hello21 world21';console.log(s.match(/d{2}/));// [ '21', index: 5, input: 'hello21 world21' ]
parseInt():转换为整型;
parseFloat():转换为浮点型;
isNaN():判断为是否不是数值;
encodeURI():对字符串进行编码;
decodeURI():
对encodeURI()函数编码过的字符串进行解码。
内置对象:
ECMA-262对内置对象是,由ECMAScript实现提供的,不依赖宿主环境的对象。
程序执行之前就已经存在了。不需要自己定义,不需要自己实例化。
定义了两个内置对象:Global和Math。