编程语言
首页 > 编程语言> > JavaScript专项练习(二)

JavaScript专项练习(二)

作者:互联网

1、以下代码执行后,控制台的输出是:

var a = 10;
function a(){}
console.log(typeof a)

答案:"number",解析:

函数提升优先级高于变量提升,所以代码等价于

function a(){}
var a;
a = 10;
console.log(typeof a)

那如果这里使用关键词let呢,代码变为

let a = 10
function a () {}
console.log(typeof a)

这里明显会报错。前面提到,函数声明会优先于变量声明,会被提升至代码块顶部,所以会先声明function a ,再执行let a = 10;,但是a已被声明过,不能再使用let 关键字进行重声明。所以这里应当注意函数声明提升的问题,即便let声明变量的语句被置于代码块顶部,但是需要注意函数声明提升。


2、下列关于 JavaScript 的说法中正确的是()

所有变量在使用之前必须做声明
JavaScript是面向对象的程序设计语言
JavaScript是解释性语言
JavaScript前身是Oak语言

答案:C,解析:

A、是错误的,JS的语法要求不是很严格,而且是弱类型的语言(声明变量没有具体类型),而且用之前不声明也没关系。
B、不完全正确,所谓面向对象,一定要有“封装、继承、多态”3大特征,JS貌似支持的不是很好,只是基于面向对象而已啦。
C、是正确的,JS文件在完成之后,不会经过任何的编译。而是在运行时去解释执行。最好的例子就是,JS中一个函数有语法的错误,但是不会因为这个局部的错误而影响其他函数运行。
D、Java的前身是Oak语言,Java和Javascript不一样


3、下面哪种方式不能改变作用域链?

with
while
try catch
eval

答案:B,解析:

A:with语句; 这两个语句都会在作用域链的前端添加一个变量对象。对WITH语句来说,将会指定的对象添加到作用域链中。对catch语句来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。

// Example: 
function builderUrl(){
    var qs="?debug=true";
    with(location){
    var url = href + qs;
        } 
    return url; 
} 

在此,with语句接受的是location对象,因此其变量对象中就包含了Location对象的所有属性和方法,而这个变量对象被添加到了作用域链的前端。builderUrl()函数中定义了一个变量qs。当在with语句中引用变量href时(实际引用的是location.href),可以在当前执行环境的变量对象中找到。当引用变量qs时,引用的则是在buildUrl()中定义的那个变量,而该变量位于函数环境的变量对象中。至于with语句内部,则定义了一个名为url的变量,因而url就成了函数执行环节的一个部分,所以可以作为函数的值被返回。
B:while的话只是在函数局部环境或者全局环境运行,并不会改变作用域链。
C:try catch红皮书第四章讲的清清楚楚:虽然执行环境的类型总共只有两种–全局和局部(函数),但还是有其他办法来延长作用域链。这么说是因为有些语句可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除。在两种情况下回发生这种现象。具体来说,就是当执行流进入下列任何一个语句时,作用域链就会得到加强:try catch语句的catch块;

D:是把字符串转换为js代码,若果字符串中有新定义 函数,那么它就有可能再建一个执行环境。


4、下列不属于javascript内置对象的是

Math
Date
RegExp
Window
Error

答案:D,解析:

JS中,可以将对象分为“内部对象”、“宿主对象”和“自定义对象”三种。
1,内部对象
js中的内部对象包括ArrayBooleanDateFunctionGlobalMathNumberObjectRegExpString以及各种错误类对象,包括ErrorEvalErrorRangeErrorReferenceErrorSyntaxErrorTypeError
其中GlobalMath这两个对象又被称为“内置对象”,这两个对象在脚本程序初始化时被创建,不必实例化这两个对象。

2.宿主对象

宿主对象就是执行JS脚本的环境提供的对象。对于嵌入到网页中的JS来说,其宿主对象就是浏览器提供的对象,所以又称为浏览器对象,如IE、Firefox等浏览器提供的对象。不同的浏览器提供的宿主对象可能不同,即使提供的对象相同,其实现方式也大相径庭!这会带来浏览器兼容问题,增加开发难度。
浏览器对象有很多,如WindowDocumenElementformimage,等等。

3.自定义对象

顾名思义,就是开发人员自己定义的对象。JS允许使用自定义对象,使JS应用及功能得到扩充


5、以下哪些语句触发了隐式的类型转换?

parseInt(12.34, 10)
0 ? 1 : 2
2e1 * 0xaa
1 + '1'

答案:ABD,解析:

parseInt() 函数可解析一个字符串,并返回一个整数。parsInt针对的是字符串值,传递非字符串参数首先会被强制类型转换为字符串。所以说,number类型的12.34发生隐式转换为string。

三元运算符,会判断?前的表达式为true或者false。所以number类型的0发生了隐式转换为boolean。

+运算发生了字符串的隐式转化。原本number类型的1,和string类型的’1’进行了+运算,连接了字符串。返回’11’。

C选项:
e是js里面指数的一种表示形式。也就是10的多少次方。
2e1等价于 2 *(10^1) = 20
2e2 等价于 2 *(10^2)= 200
0xaa是16进制的表示方法。相当于十进制的170。
这里都是number类型,发生了数字的乘法运算:20*170,没有发生类型转换。


6、下面代码执行后, arr 的值是:()

var arr=[{a:1},{}];
arr.forEach(function(item,idx){
    item.b=idx;
});

答案:B,解析:

forEach()方法是对数组中的每一项运行给定函数。
回调函数的参数item为数组当前项,idx为当前索引。
本题就是把数组每一项添加属性b,并且属性b的值为当前项的数组索引值。

另外,forEach()方法没有返回值,所以不能将 arr.foreach()像其他数组迭代方法那样赋值给某一个变量。


7、下面说法错误的是( )

每个对象都具有一个名为__proto__的属性
每个对象都具有一个名为prototype的方法
每个对象的__proto__属性指向自身构造函数的prototype
对象不具有prototype属性,只有函数才有prototype属性

答案:B,解析:

这里考察原型,js原型遵循5个规则:
1、所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了“null”以外);
2、所有的引用类型(数组、对象、函数),都有一个__proto__(隐式原型)属性,属性值是一个普通的对象;
3、所有的函数,都有一个prototype(显式原型)属性,属性值也是一个普通对象;
4、所有的引用类型(数组、对象、函数),__proto__属性值指向(完全相等)它的构造函数的“prototype”属性值;
5、当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去__proto__(即它的构造函数的prototype中)寻找。

[[prototype]]是对象的私有属性,而prototype却是只有函数才有的属性!
__proto__是JS的非标准但许多浏览器实现的属性,即[[prototype]].
也就是someObject.[[Prototype]] === someObject.__proto__,当然如果你在控制台操作的话会报错,因为浏览器并没有实现someObject.[[Prototype]]这样的操作,所以如果非要验证的话就要使用ES6支持的Object.getPrototypeOf()方法,即Object.getPrototypeOf(someObject) === someObject.__proto__


8、、某下对this对象的理解哪些是正确的 ()

this 总是指向函数的直接调用者(而非间接调用者);
如果有 new 关键字,this 指向 new 出来的那个对象;
在事件中,this 总是指向触发这个事件的对象;
this 是函数运行时自动生成的一个内部对象,只能在函数内部使用;

答案:BD,解析:
在事件中,this指向触发这个事件的对象, 特殊的是,IE中的attachEvent中的this总是指向全局对象Window
复习 this 指向:
1.函数调用时,指向window
2.以方法调用时,指向调用该方法的对象
3.使用new创建一个对象时,指向该对象
4.call,apply ,bind可以改变this指向 区别,传参不同


9、以下哪些操作会触发Reflow:()

var obj = document.getElementById(“test”);

解析:

reflow(回流)和repaint(重绘)
简要:整个在浏览器的渲染过程中(页面初始化,用户行为改变界面样式,动画改变界面样式等)reflow(回流)和repaint(重绘) 会大大影响web性能,尤其是手机页面。因此我们在页面设计的时候要尽量减少reflow和repaint。

什么是reflow和repaint

reflow:例如某个子元素样式发生改变,直接影响到了其父元素以及往上追溯很多祖先元素(包括兄弟元素),这个时候浏览器要重新去渲染这个子元素相关联的所有元素的过程称为回流。

reflow:几乎是无法避免的。现在界面上流行的一些效果,比如树状目录的折叠、展开(实质上是元素的显 示与隐藏)等,都将引起浏览器的 reflow。鼠标滑过、点击……只要这些行为引起了页面上某些元素的占位面积、定位方式、边距等属性的变化,都会引起它内部、周围甚至整个页面的重新渲 染。通常我们都无法预估浏览器到底会 reflow 哪一部分的代码,它们都彼此相互影响着。

repaint:如果只是改变某个元素的背景色、文 字颜色、边框颜色等等不影响它周围或内部布局的属性,将只会引起浏览器 repaint(重绘)。repaint 的速度明显快于 reflow

下面情况会导致reflow发生
1:改变窗口大小
2:改变文字大小
3:内容的改变,如用户在输入框中敲字
4:激活伪类,如:hover
5:操作class属性
6:脚本操作DOM
7:计算offsetWidth和offsetHeight
8:设置style属性


10、关于javascript,以下选项描述错误的是

在原型上扩展的可枚举方法,会被for in循环出来
使用object.defineProperty可向对象添加或者修改属性
每个对象都有prototype属性,返回对象类型原型的引用
通过hasOwnProperty可判断一个对象以及其原型链上是否具有指定名称的属性
原型链是JS实现继承的一种模型
For循环是按顺序的,for in 循环是不一定按顺序的

答案:,解析:

for...in:遍历对象的每一个可枚举属性,包括原型链上面的可枚举属性;
Object.keys():只遍历自身的可枚举属性,不可以遍历原型链上的可枚举属性;
Object.getOwnPropertyNames():遍历自身所有属性(不论是否是可枚举的);不包括原型链。

AD:所有继承了 Object 的对象都会继承到hasOwnProperty 方法。这个方法可以用来检测一个对象是否含有特定的自身属性;和 in 运算符不同,该方***忽略掉那些从原型链上继承到的属性。所以A对D错

B:应该是Object.defindeProperty是给对象添加或修改属性的方法,Object是 js 的内置对象,而object是一个变量名,这一点还是有区别的,题目不够严谨吧

C:创建的每一个函数都有一个prototype(原型)属性。浏览器实现的访问对象的[[prototype]]内部属性的方式是__proto__属性。

var obj = Object.create(null)
console.log(obj.__proto__) // undefined

这个方式是以null为原型创建的对象,然而null并没有原型对象,所以这样创建出来的对象也没有原型对象,所以obj没有__proto__属性。
F:红宝书上说道for-in循环出的属性名顺序是不可预测的,返回的先后次序会因浏览器而异


11、以下符合 ES6 写法的有:()

// A
class Foo
{
	constructor() {return Object.create(null);}
}
Foo()

// B
var m=1;
export m;

// C
export var firstName=’Michael’;

// D
在A模块中export{readFile}后,在B模块中import readFile from ‘A’可以获取到readFile

答案:C,解析:

A:类必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行。
B:export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。

// 报错
export 1;
// 报错
var m = 1;
export m;

上面两种写法都会报错,因为没有提供对外的接口。第一种写法直接输出 1,第二种写法通过变量m,还是直接输出 1。1只是一个值,不是接口。
正确的写法是下面这样。

// 写法一
export var m = 1;
// 写法二
var m = 1;
export {m};
// 写法三
var n = 1;
export {n as m};

D:A模块对外暴露了一个对象,引入的时候需要使用解构赋值

import {readFile} from ‘A'

12、关于这段代码正确的结论是:()

var F=function(){};
Object.prototype.a=function(){};
Function.prototype .b=function(){};
var f=new F();
f能取到a,但取不到b
f能取到a,b
F能取到b,不能取到a
F能取到a,不能取到b

答案:D,解析:

浅显一点的方法(非考点): 用instanceof判别,

f instanceof Object  // true ;
 f instanceof Function //false ;

由此可见用new操作符创建的f只是对象,所以只能继承于Object.prototype.

网上有一道美团外卖的面试题是这样的:

Function.prototype.a = 'a';
Object.prototype.b = 'b';
function Person(){};
var p = new Person();
console.log('p.a: '+ p.a); // p.a: undefined
console.log('p.b: '+ p.b); // p.b: b  问为什么?

有不少同学第一眼看上去就觉得很疑惑,p不是应该继承了Function原型里面的属性吗,为什么p.a返回值是undefined呢?
其实,只要仔细想一想就很容易明白了,Person函数才是Function对象的一个实例,所以通过Person.a可以访问到Function
原型里面的属性,但是new Person()返回来的是一个对象,它是Object的一个实例,是没有继承Function的,所以无法访问
Function原型里面的属性。但是,由于在js里面所有对象都是Object的实例,所以,Person函数可以访问到Object原型里面的
属性,Person.b => 'b'

推荐几篇文章, 我认为讲原型和原型链讲得比较好的

最详尽的 JS 原型与原型链终极详解,没有「可能是」。(一)(二)(三)


13、要在10秒后调用checkState,下列哪个是正确的

function checkState(){
 alert("liyuming"); 
 }
window.setTimeout(checkState, 10);
window.setTimeout(checkState, 10000);
window.setTimeout(checkState(), 10);
window.setTimeout(checkState(), 10000);

答案:B,解析:

带括号立即执行,不带括号返回函数本身。

window.setTimeout(checkState(), 10000); //立即被调用

window.setTimeout(checkState, 10000); // 10s后被调用

window.setTimeout(“checkState()”, 10000); //10s后被调用 注意和第一个的区别 有引号。其实第三个也是立即执行(10秒后立即执行),第三个是字符串形式,js引擎会解析两次,所以会比第一个慢一点。


14、在浏览器控制台执行以下代码,输入的结果是()

function test(){
    var n = 4399;
    function add(){
        n++;
        console.log(n);
    }
    return {n:n, add:add}
}

var result = test();  //{n:4399, add:fn}
var result2 = test(); //{n:4399, add:fn}
result.add(); //4400
result.add(); //4401
console.log(result.n);//4399
result2.add();//4400

答案:4400,4401,4399,4400,解析:

test构成了一个闭包,resultresult2拥有不同的堆内存空间。result===result2返回的是false,resultresult2之所有有各自的作用域是两次调用了函数后必然产生的结果啊,两次调用函数,产生两个闭包留在内存里。所以最后result2.add()结果是4400。

闭包函数的问题,可参考阮一峰老师的一篇博文(http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html),简单易懂,借用阮老师博客中所写,闭包的两个最大的用处:一个是可以读取到函数内部的变量,另一个就是让这些变量的值始终保持在内存中,具体可以测试。第二个用途就解释了同一个作用域中答案2会在1的基础上进行+1操作。

前两个没啥好说的,懵逼点在第三个,这里的n是一个值类型变量,这里{n:n}是对变量n里的值进行缓存, n是基本类型,存的是值,不是引用。不是本身n这个指针变量,所以生成n时候n里存的值是多少返回的对象里值就是多少。


15、如果需要匹配包含文本的元素,用下面哪种方法来实现?

text()
contains()
input()
attr(name)

答案:A,解析:

text()是jQuery中的方法,可是设置或返回被选元素的文本内容
:contains选择器,选取包含指定字符串的元素,字符串也可以是文本
:input()选择器,选取表单元素
attr(name,value)属性操作,设置或返回被选元素的属性和属性值
本题选B


16、在jquery中,如果想要获取当前窗口的宽度值,下面哪个是实现该功能的?

width()
width(val)
width
innerWidth()

答案:A,解析:

height() - 设置或返回元素的高度
innerWidth() - 返回元素的宽度(包含 padding)
innerHeight() - 返回元素的高度(包含 padding)
outerWidth() - 返回元素的宽度(包含 padding 和 border)
outerHeight() - 返回元素的高度(包含 padding 和 border)


17、如何获取下面表单 select域的选择部分的文本?

<form name="formA">
<select name="a" size="1" id=”obj”>
<option value="a">1</option>
<option value="b">2</option>
<option value="c">3</option>
</select>
</form> 

答案:C,解析:

id选择器,可直接选择
obj.value 返回当前option节点的value
obj.text 返回当前option节点的文本
obj,options 获得obj下的所有options节点,为一个类数组
obj.selectedIndex 返回当前option节点的索引


18、在jquery中想要找到所有元素的同辈元素,下面哪一个是可以实现的?

eq(index)
find(expr)
siblings([expr])
next()

答案:C,解析:

jQuery siblings() 方法
siblings()方法返回被选元素的所有同胞元素。

下面的例子返回 <h2> 的所有同胞元素:

$(document).ready(function(){
  $("h2").siblings();
});

您也可以使用可选参数来过滤对同胞元素的搜索。

下面的例子返回属于 <h2>的同胞元素的所有<p>元素:

$(document).ready(function(){
  $("h2").siblings("p");
});

jQuery next() 方法
next()方法返回被选元素的下一个同胞元素。

该方法只返回一个元素。

下面的例子返回 <h2>的下一个同胞元素:

$(document).ready(function(){
  $("h2").next();
});

jQuery find()方法
find()方法返回被选元素的后代元素,一路向下直到最后一个后代。

下面的例子返回属于 <div>后代的所有<span>元素:

$(document).ready(function(){
  $("div").find("span");
});

19、以下Js程序的输出是什么()

<SCRIPT LANGUAGE="JavaScript">
    var a="undefined";
    var b="false";
    var c="";
    function assert(aVar){
        if(aVar)     
            alert(true);
        else  
            alert(false);
    }
    assert(a);
    assert(b);
    assert(c);
</SCRIPT>

答案:true,true,false,解析:

a,b均为非空字符串,c为空字符串

ECMAScript会自动调用Boolean()转换函数将结果转换为布尔值。转换规则为:

数据类型转换为true转换为false
booleantruefalse
String任何非空字符串空字符串
Number任何非零数字值0和NaN
Object任何对象null
Array非空数组空数组
Undefined/undefined

20、如何遍历下面的 my_data 对象?

var my_data={a:’Ape’, b:’Banana’, c:’Citronella’};
for(var key in my_data) {}
foreach(my_data as key=>value) {}
for(var i=0;i<my_data.length;i++) {}
全不正确

答案:A,解析:

A 是for in方法遍历对象(可配合hasOwnProperty)
B JS的的遍历方法是obj.forEach(回调函数)

// 用forEach遍历对象
Object.keys(obj).forEach(function(key){
console.log(key,obj[key]);
});

C 是遍历数组的方法

标签:__,专项,练习,函数,对象,JavaScript,var,元素,属性
来源: https://blog.csdn.net/qq_44721831/article/details/120688928