functionisArray(obj){returnobj.__proto__===Array.prototype;}基本思想:实例如果是某个构造函数构造出来的那么它的__proto__是指向构造函数的prototype属性
classAnimal{constructor(name){this.name=name;};eat(){console.log(this.name+'正在吃东西');};}//继承动物类classCatextendsAnimal{catchMouse(){console.log(`${this.name}正在捉老鼠`);}}varcat=newCat('Tom猫');cat.catchMouse();//Tom猫正在捉老鼠原型继承functionAnimal(name){this.name=name;}Animal.prototype.eat=function(){console.log(this.name+'正在吃东西')};functionCat(furColor){this.furColor=furColor;};Cat.prototype=newAnimal();lettom=newCat('black');console.log(tom)构造继承寄生组合式继承实例继承call、apply、bind之间的关系bind,apply,call三者都可以用来改变this的指向;
总结一下,一个异步过程通常是这样的:
所以,从主线程的角度看,一个异步过程包括下面两个要素:
它们都是在主线程上调用的,其中注册函数用来发起异步过程,回调函数用来处理结果。
举个具体的例子:
setTimeout(fn,1000);其中的setTimeout就是异步过程的发起函数,fn是回调函数。
注意:前面说的形式A(args...,callbackFn)只是一种抽象的表示,并不代表回调函数一定要作为发起函数的参数。
例如:
varxhr=newXMLHttpRequest();xhr.onreadystatechange=xxx;//添加回调函数xhr.open('GET',url);xhr.send();//发起函数发起函数和回调函数就是分离的。
eval()函数可计算某个字符串,并执行其中的的JavaScript代码。
console.log(Object.values('abc'));//=>['a','b','c']console.log(Array.from('abcd'));console.log([...'abcd']);console.log('abcd'.split(''));console.log([].slice.call('abcd'));构造元素重复的数组可以使用array.fill:
letuser=newObject();//addingapropertyuser.name='Anil';user.age=25;console.log(user);deleteuser.age;console.log(user);解释一下什么是promise?promise是js中的一个对象,用于生成可能在将来产生结果的值。值可以是已解析的值,也可以是说明为什么未解析该值的原因。
promise可以有三种状态:
一个等待状态的promise对象能够成功后返回一个值,也能失败后带回一个错误当这两种情况发生的时候,处理函数会排队执行通过then方法会被调用
1.使用setfunctionuniquearray(array){letunique_array=Array.from(set(array))returnunique_array;}
2.使用filter
functionunque_array(arr){letunique_array=arr.filter(function(elem,index,self){returnindex==self.indexOf(elem);})returnunique_array;}console.log(unique_array(array_with_duplicates));3.使用for循环
Arraydups_names=['Ron','Pal','Fred','Rongo','Ron'];functiondups_array(dups_names){letunique={};names.forEach(function(i){If(!unique[i]){unique[i]=true;}});returnObject.keys(unique);}//Ron,Pal,Fred,RongoDups_array(names);undefined,null和undeclared有什么区别?1.null表示"没有对象",即该处不应该有值,转为数值时为0。典型用法是:
(1)作为函数的参数,表示该函数的参数不是对象。
(2)作为对象原型链的终点。
2.undefined表示"缺少值",就是此处应该有一个值,但是还没有定义,转为数值时为NaN。典型用法是:
(2)调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
3.undeclared:js语法错误,没有申明直接使用,js无法找到对应的上下文。
1、对于string,number等基础类型,==和===有区别1)不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等。2)同类型比较,直接进行“值”比较,两者结果一样。2、对于Array,Object等高级类型,==和===没有区别
进行“指针地址”比较。
3、基础类型与高级类型,==和===有区别1)对于==,将高级转化为基础类型,进行“值”比较。2)因为类型不同,===结果为false。
事件捕获和冒泡:在HTMLDOMAPI中,有两种事件传播方法,它们决定了接收事件的顺序。两种方法是事件冒泡和事件捕获。第一个方法事件冒泡将事件指向其预期的目标,第二个方法称为事件捕获,其中事件向下到达元素。
事件捕获
捕获过程很少被使用,但是当它被使用时,它被证明是非常有用的。这个过程也称为滴流模式。在这个过程中,事件首先由最外层的元素捕获,然后传播到最内部的元素。例如:
事件冒泡
冒泡的工作原理与冒泡类似,事件由最内部的元素处理,然后传播到外部元素。
module和exports是Node.js给每个js文件内置的两个对象。可以通过console.log(module)和console.log(exports)打印出来。如果你在main.js中写入下面两行,然后运行$nodemain.js:
console.log(exports);//输出:{}console.log(module);//输出:Module{...,exports:{},...}(注:...代表省略了其他一些属性)从打印咱们可以看出,module.exports和exports一开始都是一个空对象{},实际上,这两个对象指向同一块内存。这也就是说module.exports和exports是等价的(有个前提:不去改变它们指向的内存地址)。
例如:exports.age=18和module.export.age=18,这两种写法是一致的(都相当于给最初的空对象{}添加了一个属性,通过require得到的就是{age:18})
import和exports帮助咱们编写模块化的JS代码。使用import和exports,咱们可以将代码分割成多个文件。import只允许获取文件的某些特定变量或方法。可以导入模块导出的方法或变量。
//index.jsimportname,agefrom'./person';console.log(name);console.log(age);//person.jsletname='Sharad',occupation='developer',age=26;export{name,age};如何在JS中克隆对象Object.assign()方法用于在JS中克隆对象。如:
varx={myProp:"value"};vary=Object.assign({},x);如何在JS中编码和解码URL?varuri="myprofile.phpname=sammer&occupation=pāntiNG";varencoded_uri=encodeURI(uri);decodeURI(encoded_uri);BOM和DOM的关系BOM全称BrowserObjectModel,即浏览器对象模型,主要处理浏览器窗口和框架。
DOM全称DocumentObjectModel,即文档对象模型,是HTML和XML的应用程序接口(API),遵循W3C的标准,所有浏览器公共遵守的标准。
JS是通过访问BOM(BrowserObjectModel)对象来访问、控制、修改客户端(浏览器),由于BOM的window包含了document,window对象的属性和方法是直接可以使用而且被感知的,因此可以直接使用window对象的document属性,通过document属性就可以访问、检索、修改XHTML文档内容与结构。因为document对象又是DOM的根节点。
可以说,BOM包含了DOM(对象),浏览器提供出来给予访问的是BOM对象,从BOM对象再访问到DOM对象,从而js可以操作浏览器以及浏览器读取到的文档。
内置方法返回值CharAt()它返回指定索引处的字符。Concat()它连接两个或多个字符串。forEach()它为数组中的每个元素调用一个函数。indexOf()它返回指定值第一次出现时调用字符串对象中的索引。length()它返回字符串的长度。pop()它从数组中删除最后一个元素并返回该元素。push()它将一个或多个元素添加到数组的末尾,并返回数组的新长度。reverse()反转数组元素的顺序。
undefined是基本数据类型表示未定义缺少的意思。
null是引用数据类型,是对象,表示空对象
undefined是从null派生出来的所以undefined==null为true
call和apply可以用来重新定义函数的执行环境,也就是this的指向;call和apply都是为了改变某个函数运行时的context,即上下文而存在的,换句话说,就是为了改变函数体内部this的指向。
call()调用一个对象的方法,用另一个对象替换当前对象,可以继承另外一个对象的属性,它的语法是:
Function.call(obj[,param1[,param2[,[,...paramN]]]]);说明:call方法可以用来代替另一个对象调用一个方法,call方法可以将一个函数的对象上下文从初始的上下文改变为obj指定的新对象,如果没有提供obj参数,那么Global对象被用于obj
apply()和call()方法一样,只是参数列表不同,语法:
Function.apply(obj[,argArray]);说明:如果argArray不是一个有效数组或不是arguments对象,那么将导致一个TypeError,如果没有提供argArray和obj任何一个参数,那么Global对象将用作obj。
有许多方法可以用来清空数组:
方法一:
arrayList=[]上面的代码将把变量arrayList设置为一个新的空数组。如果在其他任何地方都没有对原始数组arrayList的引用,则建议这样做,因为它实际上会创建一个新的空数组。咱们应该小心使用这种清空数组的方法,因为如果你从另一个变量引用了这个数组,那么原始的引用数组将保持不变。
方法二:
arrayList.length=0;上面的代码将通过将其length设置为0来清除现有数组。这种清空数组的方式还会更新指向原始数组的所有引用变量。因此,当你想要更新指向arrayList的所有引用变量时,此方法很有用。
方法三:
arrayList.splice(0,arrayList.length);这处方法也行,当然这种清空数组的方法也将更新对原始数组的所有引用。
方法四:
while(arrayList.length){arrayList.pop();}上面的实现也可以空数组,但通常不建议经常使用这种方式。
varelements=document.querySelectorAll("p");//NodeListvararrayElements=[].slice.call(elements);//现在NodeList是一个数组vararrayElements=Array.from(elements);//这是另一种转换NodeList到Array的方法JavaScript判断一个变量是对象还是数组?typeof都返回object
在JavaScript中所有数据类型严格意义上都是对象,但实际使用中我们还是有类型之分,如果要判断一个变量是数组还是对象使用typeof搞不定,因为它全都返回object。
第一,使用typeof加length属性
数组有length属性,object没有,而typeof数组与对象都返回object,所以我们可以这么判断
vargetDataType=function(o){if(typeofo=='object'){if(typeofo.length=='number'){return'Array';}else{return'Object';}}else{return'paramisnoobjecttype';}};第二,使用instanceof
利用instanceof判断数据类型是对象还是数组时应该优先判断array,最后判断object。
vargetDataType=function(o){if(oinstanceofArray){return'Array'}elseif(oinstanceofObject){return'Object';}else{return'paramisnoobjecttype';}};如何将一个数组打乱方法1:arr.sort(()=>Math.random()-0.5);
sort方法使用了插入排序(目标长度小于10)和快排,元素之间的比较远小于n(n-1)/2,因此有些元素间没有随机交换的可能,使得该方法不够随机。
方法2:Fisher-YatesShuffle,复杂度为O(n)。从后向前遍历,不断将当前元素与随机位置的元素(除去已遍历的部分)进行交换。
先将img标签的src链接设为同一张图片(比如某空白图片),然后给img标签设置自定义属性(比如data-src),并将真正的图片地址存储在其中。当js监听到该图片元素进入可视窗口时(获取img节点距离浏览器顶部的距离,如果小于或等于浏览器窗口的可视高度即进入),再将自定义属性中的地址存储到src属性中,达到懒加载的效果。这样不仅可以减轻服务器压力,也可以提高用户体验。
html标签只包含head和body两个标签,解析时,所有标签都会解析进这两个标签里边。body之前的任何位置都会解析进head里边,之后的都会解析进body里边。
共有:defer和async、动态创建DOM方式(用得最多)、使用jQuery的getscript方法、使用settimeout延迟方法、让js最后加载defer属性:(页面load后执行)
HTML4.01为