当前位置: 首页 > 后端技术 > Node.js

JavaScript基本技能--访谈宝典

时间:2023-04-03 20:05:48 Node.js

JavaScript数据类型JavaScript中的基本数据类型有哪些undefined,null,number,string,boolean,symbol(es6new)为什么没有object,array,function?它们都是复杂的数据类型。好像有点字面意思。typeof运算符对各数据类型string的运算结果------------------------stringnumber-----------------------数字布尔值--------------------布尔函数----------------------functionundefined--------------------undefinednull----------------------------object(空值表示空对象指针)array------------------------objectobject------------------------object因此,有时typeof不能准确判断一个变量的数据类型。如何区分null和undefined从上面可以看出,使用typeof可以判断null和undefined之间的区域。也可以通过null===undefined来判断。如何准确判断变量的数据类型JavaScript中的所有变量都可以作为对象使用,除了两个例外:null和undefined。所以我们可以使用对象原型链上的toString方法将一个变量转换成字符串,然后区分它们的类型。Object.prototype.toString.call(*);例子:Object.prototype.toString.call(null)//"[objectNull]"Object.prototype.toString.call(undefined)//"[objectUndefined]"*在IE8中,两者的结果都是"[objectNull]"Object]",所以我们也可以用这个方法来区分null和undefined对象的创建和使用varobj1={x:1,'longname':2};varobj2=newObject();varobj3=Object.create(obj2);accessobjectpropertiesobj1.x//1obj1["longname"]//2注意,如果属性名有空格或者破折号,只能使用该方法删除对象属性deleteobj1.x//唯一删除方式objectproperties就是去掉继承和原型链前面我们说过,JavaScript中的一切都可以认为是一个对象。每个对象都有一个私有原型。它持有到另一个对象的链接,称为它的原型(prototypeobject)。原型对象又拥有自己的原型,依此类推,直到原型为null的对象。继承上面创建对象可以看到使用Object.create可以实现继承。你也可以使用Object.prototype来实现继承。示例:varobj={a:1}functionP(name){//构造函数this.name=name}P.prototype=obj//继承objvarp=newP('wesley');//instanceobjectp.a//1其次,我们也可以使用es6中新语法class等关键字来实现继承。原型链原型链的定义复杂而笨拙。我们可以通过很多浏览器实现的JavaScript的非标准属性__proto__来理解原型链。对象的__proto__属性是该对象构造函数的原型属性。基于上述构造函数继承代码:console.log(p.__proto__===P.prototype)//trueconsole.log(P.prototype===obj)//trueconsole.log(P.prototype.__proto__===Object.prototype)//trueconsole.log(Object.prototype.__proto__===null)//真正的作用域和命名空间如果你了解es6的let用法,那么你应该只需要JavaScript有块级作用域和函数作用域.简单的说,通常我们使用var创建的变量都属于函数作用域。什么是块级作用域?其实可以简单理解为一对花括号包围的代码块作用域。JavaScript中没有明确的命名空间定义,这意味着所有对象都定义在一个全局共享的命名空间下。每次引用变量时,JavaScript都会向上遍历整个作用域,直到找到该变量。如果到达全局范围但仍未找到变量,则会引发ReferenceError异常。隐式全局变量foo1=1;varfoo2=2;//如果在函数内部,则为局部变量letfoo3=3;//如果在代码块内部,则为局部变量可以理解下面代码的执行结果letandvarvara=[];对于(vari=0;i<10;i++){a[i]=function(){console.log(i);};}a[6]();//10如果使用letvara=[];for(leti=0;i<10;i++){a[i]=function(){console.log(i);};}a[6]();//6变量声明提升var表达式和函数声明都将被提升到当前作用域的顶部。请注意,let表达式不会被提升。这也正好说明下面的代码可以正常执行:test();functiontest(){console.log(a)vara=5;}可以理解为改进后的代码:functiontest(){vara;//此时a是undefined,所以我们打印的时候是undefinedconsole.log(a)a=5;}test();没有var声明的变量提升示例:test();functiontest(){b=5}console.log(b)//5可以理解为提升后:varb;//undefined(functiontest(){b=5})()console.log(b)closure闭包是一个非常重要的JavaScript属性,这意味着当前作用域始终可以访问外部作用域中的变量。可以理解为访问本来不能访问的东西,就是闭包。示例:functionCounter(start){varcount=start;返回{增量:函数(){计数++;},get:function(){返回计数;}}}varfoo=Counter(4);//此时如果我们直接在外部使用console.log(count),就会抛出错误foo.increment();foo.get();//5这里,Counter函数返回两个闭包,函数increment和函数get。这两个函数都维护对Counter函数内部范围的引用。所以如果需要访问或获取Counter中的变量count,只能使用闭包。关于闭包,有一个经典的例子:for(vari=0;i<10;i++){setTimeout(function(){console.log(i);},1000);}//1010*想想为什么.详情请看:https://segmentfault.com/a/11...setTimeout和setInterval由于JavaScript是异步的,所以可以使用setTimeout和setInterval来规划执行函数。*注意:定时处理程序不是ECMAScript标准,它们是在DOM(文档对象模型)中实现的。函数foo(){}varid=setTimeout(foo,1000);//返回一个大于零的数字当调用setTimeout时,它返回一个ID并安排foo函数在未来大约1000毫秒被调用。foo函数只会执行一次。因此,一般我们可以认为setTimeout执行的函数会异步执行。