JS刷题总结

2021/11/18

第一题

在这里插入图片描述
结果:15岁的小红在操场上运动
考点:this指向,call,apply,bind问题
分析:使用了call方法,因此this指向了p2

this指向:

前提:

  • this永远指向一个对象
  • this的指向完全取决于函数调用的位置
  • this指的是函数运行时所在的环境

参考:this的原理

总结:

函数调用模式:

this被绑定为全局对象,在浏览器环境下就是window对象

function a(){
    
    
	let a = 'hello';
	console.log(this.hello);//undefined
	console.log(this);//window
}
a();
方法调用模式:

当一个函数被保存为一个对象的属性时,那么这个函数就称为这个对象的方法。当一个方法被调用时,this被绑定到这个对象上

let o={
    
    
	name: 'hello',
	sayName: function(){
    
    
		console.log(this.name)//hello
		console.log(this) //o这个对象
	} 
}
o.sayName();

this指向的对象为o

let o={
    
    
	name:'hello',
	b:{
    
    
		name: 'world',
		sayName: function(){
    
    
			console.log(this.name)//world
			console.log(this)//b这个对象
		} 
	}	
}
o.b.sayName();

this指向的对象为b,因为是o.b调用的这个函数

let name='我是最外面的name';
let o={
    
    
	name:'hello',
	b:{
    
    
		name: 'world',
		sayName: function(){
    
    
			console.log(this.name)//我是最外面的name
			console.log(this)//window
		} 
	}	
}
let t=o.b.fn;
t();

t是全局变量,在全局环境下执行,this指向window

构造函数调用模式:

构造函数和普通函数的区别就是调用方式不同,普通函数是直接调用,而构造函数需要使用new关键字来调用。

function Person(){
    
    
  alert(this);
}
//普通函数调用
var per1 = Person();//this是window
console.log(per1);//输出undefined,因为per1接受的是函数Person()的返回值,而Person()没有返回值,所以undefined

//构造函数调用
var per2 = new Person();//this是新建的对象 Person{}
console.log(per2);//输出Person(对象)

  function Person(){
    
    
            this.name = "Tiny Colder";
            var age = 22;
            window.age = 22;
        }
        var p = new Person();
        alert(p.name)//Tiny Colder;
        alert(p.age)//undefined;
        alert(window.age)//22;

调用一个构造函数,执行流程分为4步:

  • 立刻创建一个新的对象(一个Object对象实例):使用了new关键字,在堆内存开辟了一个新的空间去创建对象
  • 将新建的对象设置为函数中的this,在构造函数中可以使用this来引用新建的对象(将构造函数的执行对象赋给新生成的这个实例)。
  • 逐行执行函数中的代码
  • 将新建的对象作为返回值返回

因此:在构造函数中,new出一个对象时,this指向这个构造函数,new关键字会改变this的指向。当用new关键字,返回的是一个对象,this指向的就是那个返回的对象;如果返回的不是对象,this还是指向函数的实例,虽然null属于对象,但是返回null依然指向函数实例。

如果被调用的函数没有显式的 return 表达式(仅限于返回对象),则隐式的会返回 this 对象 - 也就是新创建的对象。

可参考 构造函数中this的指向问题

function Fn(){
    
    
	this.name='hello';
}
let f=new Fn();
console.log(f.name);//hello
没有显示的return表达式,因此this指向的是返回的创建的Fn实例
function Fn(){
    
    
	this.name='hello';
	return {
    
    }
}
let f=new Fn();
console.log(f.name);//undefined
function Fn(){
    
    
	this.name='hello';
	return function(){
    
    };
}
let f=new Fn();
console.log(f.name);//null
function Fn(){
    
    
	this.name='hello';
	return 1;
}
let f=new Fn();
console.log(f.name);//hello
function Fn(){
    
    
	this.name='hello';
	return undefined;
}
let f=new Fn();
console.log(f.name);//hello
function Fn(){
    
    
	this.name='hello';
	return null;
}
let f=new Fn();
console.log(f.name);//hello
function Fn(){
    
    
	this.name='hello';
	return [];
}
let f=new Fn();
console.log(f.name);//undefined

总结:
显式的返回以下值:undefined, null, boolean, number等基础类型,并不会代替 new 式调用的默认行为。

但显式返回以下值 对象,复杂类型:{},[],RegExp, Date, Function,均会代替 new 调用的默认返回值 this.

call和apply调用模式

JS中,函数也是对象,所有函数对象都有两个方法:apply和call,这两个方法可以让我们构建一个参数数组传递给调用函数,也允许我们改变this的值

var name='obj1';
var o={
    
    
	name:'obj2'
};
function sayName(){
    
    
	console.log(this.name);
}
sayName();//obj1
sayName.apply();//obj1
sayName.apply(o);//obj2
sayName.call(o);//obj2
sayName.call();//obj1

call和apply的作用都是改变this作用域,都是在特定作用域中调用函数。当一个对象没有某个方法,而其他对象有,我们就可以使用call或apply实现某个方法的复用。

call和apply使用方法基本相同,唯一不同之处就是它们的参数规则:

call方法接受一个参数列表,将实参在对象之后依次传递fun.call(obj,2,4)
apply方法接受一个包含多个参数的数组,需要将实参封装到数组中统一传递fun.apply(obj,[2,4])

第二题

在这里插入图片描述
知识点:正则表达式
[]里的内容是或的关系:[ab]意为a或b;所以[0-9a-fA-F]意为可以是数字也可以是大小写字母
{}前面的内容重复多少次

第三题

在这里插入图片描述
答案:undefined

解析:

let和var区别:

  • 如果在全局作用域中用var声明,此变量会默认成为window的一个属性,let声明的变量是不会添加到window对象中的;
  • let声明的范围是块级作用域(用{}包含的区域),var声明的范围是函数作用域;
  • var声明的变量有变量提升的特性,而let没有
  • var可以允许重复声明相同变量,后者会覆盖前者,而let不能重复声明相同变量

var声明的对象有变量提升的特性,因此a在window上定义了,但没有赋值,a在window里为true,取反为false,因此直接alert(a)。为undefined

第四题

在这里插入图片描述
结果为:5 5 5 5 5
解析:requestAnimationFrame为异步执行(宏任务)的,因此for循环中的requestAnimationFrame会在循环退出的时候才执行其中的回调,注意循环退出的时候i的值为5

如果是为let,结果就变为0,1,2,3,4。var为函数作用域,异步函数在for循环结束后还未执行,函数作用域的 i 就变为了5。let为块级作用域,每一次for循环都会产生一个块级作用域

第五题

在这里插入图片描述
解析:

Ajax不是新的编程语言,而是一门提供网页局部刷新的技术。
Ajax最大的优点是在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容。
Ajax技术核心就是XMLHttpRequest对象。

Ajax技术的工作原理:可以分成3步

  1. 创建Ajax对象:var xhr = new XMLHttpRequest();

  2. xhr 发送请求:

    xhr.open(‘get’,‘test.html’,‘true’);
    xhr.send();

  3. xhr获取响应:

  xhr.onreadystatechange = function(){
    
    
 	if(xhr.readystate == 4){
    
    //请求的状态码
          /*
             0:请求还没有建立(open执行前)
             1:请求建立了还没发送(执行了open)
             2:请求正式发送(执行了send)
             3:请求已受理,有部分数据可以用,但还没有处理完成
             4:请求完全处理完成
        */
        alert(xhr.responseText);//返回的数据
   }
}

可以看到,send()前是open()

2021/11/19

第一题

在这里插入图片描述
顺序为CBAD
解析:

  1. 首先,Node在当前目录下查找package.json(CommonJS包规范定义的包描述文件),通过JSON.parse()解析出包描述对象,从中取出main属性指定的文件名进行定位。如果文件缺少扩展名,将会进入扩展名分析的步骤。
  2. 而如果main属性制定的文件名错误,或者压根没有package.json文件,Node会将index当做默认文件名,然后依次查找index.js、index.node、index.json.
  3. 如果在目录分析的过程中没有定位成功任何文件,则自定义模块进入下一个模块路径进行查找。如果模块路径数组都被遍历完毕,依然没有查找到目标文件,则会抛出查找失败异常。
  4. 按照上面的思路,首先应该查找package.json文件,看看里面有没有核心模块,应该是C最先,othermodule不是核心模块,那么接着应该进入扩展名分析的步骤,就应该是查找othermodule. js,对应B,紧接着就是以index为默认文件名,也就是A,再接下来就是上一个文件目录D了,

在这里插入图片描述

第二题

在这里插入图片描述
总结:

node节点有几个常用的属性

  • firstChild
  • lastChild
  • nextSibling:下一个兄弟节点
  • previousSibling:前一个兄弟节点
    这些都是属性,都不需要添加括号的。

第三题

在这里插入图片描述
总结:

  • 两个对象不相等 除非指向同一个对象地址
  • 恒等不会进行数据类型转换
  • 双等会进行数据类型转换,字符串转换成数值在进行对比

第四题在这里插入图片描述

Object.keys()

该方法返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for…in 循环遍历该对象时返回的顺序一致 。如果对象的键-值都不可枚举,那么将返回由键组成的数组。

String.prototype.split()

split() 方法使用指定的分隔符字符串将一个String对象分割成字符串数组,以将字符串分隔为子字符串,以确定每个拆分的位置。

Array.prototype.join()

join() 方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。

Promise.all()

Promise.all(iterable) 方法返回一个 Promise 实例(对象),此实例在 iterable 参数内所有的promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);
如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。

第五题

下面哪些方式在同一个窗口下能够检测一个js对象是数组类型?( )
在这里插入图片描述
检测数据的类型的方法:

  1. typeof:只能检测基本的数据类型,注意:正则,{},[],null输出结果都为object
  2. instanceof:检测当前实例是否属于某个类,返回值为布尔值
  3. Array 为 js 的原生对象,它有一个静态方法:Array.isArray(),能判断参数是否为数组, isNaN() 判断是否是NaN
  4. Object.prototype.toString.call([value]);获取 Object.portotype 上的 toString 方法,让方法的 this 变为需要检测的数据类型值,并且让这个方法执行;在Number、String、Boolean、Array、Function、RegExp…这些类的原型上都有一个toString方法:这个方法就是把本身的值转化为字符串;在Object这个类的原型上也有一个方法toString,但是这个方法并不是把值转换成字符串,而是`返回当前值得所属类详细信息,固定结构:’[object 所属的类]’
var obj = {
    
    name: '珠穆朗玛峰'}
obj.toString() // "[object Object]"
Object.prototype.toString.call(12) // "[object Number]"
Object.prototype.toString.call(true) // "[object Boolean]"

2021/11/20

第一题

在这里插入图片描述
AMD和CMD都是浏览器端的js模块化规范,分别由require.js和sea.js实现。 CommonJS是服务器端的js模块化规范,由NodeJS实现。

第二题

在这里插入图片描述
解析:
undefined值是通过null派生出来的,相等时它会自动转化为null,所以返回true。不过如果用严格比较符 ===,不发生转化,将返回false。
es6中的Symbol属于新的js数据类型

第三题

在这里插入图片描述
解析:
call()方法和apply()方法的作用相同,他们的区别在于接收参数的方式不同。对于call第一个参数是this值没有变化,变化的是其余参数都直接传递给函数。(在使用call()方法时,传递给函数的参数必须逐个列举出来。使用apply时,传递给函数的是参数数组

function add(c, d){
    
    
	return this.a + this.b + c + d;
}
var o = {
    
    a:1, b:3};
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34

第四题

在这里插入图片描述
解析:

  • parseFloat():parseFloat() 函数可解析一个字符串,并返回一个浮点数。A选项的结果为0.6000000000000001
  • toFixed :把数字转换为字符串,结果的小数点后有指定位数的数字,按四舍五入取值。var num = 5.56789;var n=num.toFixed(2);结果为5.57。B选项的结果为0.6
  • Math.round():round() 方法可把一个数字舍入为最接近的整数,按四舍五入取值。C选项的结果为1
  • toPrecision():把数字格式化为指定的长度,返回的是一个字符串。var num = new Number(13.3714);var n=num.toPrecision(2);结果为13。0.08.toPrecision(1)结果为‘0.08’,0.8.toPrecision(1)结果为’0.8’;0.18.toPrecision(1)结果为0.2;D选项中先使用toPrecision将0.8转为字符0.8,在使用parseFloat进项解析,返回一个浮点数0.8

第五题

在这里插入图片描述
解析:
exec() 方法用于检索字符串中的正则表达式的匹配。
返回值:返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。

所以"e".exec(“hello”)中,"e"是正则表达式,“hello"是检索的字符串。在"hello"字符串中,能够匹配到"e”。因此document.write(“e”);最后结果为e。

第六题

在这里插入图片描述

  • 非严格模式下JavaScript语句中“this”默认指向全局对象(window)。
  • this绑定的优先级是new>bind>call(apply)>obj.func()>默认绑定
  • obj.log = console.log;//在obj对象中创建了一个函数(即console.log)的引用log,因为是个函数的引用,如果想要执行可以有两种方法,第一种是后边加(),第二种是使用apply()或者call(),二者第一个参数都是this,接下来的参数apply是参数数组或者是"arguments",而call的参数是直接的参数值
  • obj.log.call(console,this);//如上所述,call的第二个参数是要被传入obj.log()的参数,这行代码其实可等价于console.log(this),而因为这三行代码都是在global环境下定义的(不是函数中的局部变量),所以this就是window.

第七题

在这里插入图片描述
解析:
JS中,可以将对象分为“内部对象”、“宿主对象”和“自定义对象”三种。

内部对象

js中的内部对象包括Array、Boolean、Date、Function、Global、Math、Number、Object、RegExp、String以及各种错误类对象,包括Error、EvalError、RangeError、ReferenceError、SyntaxError和TypeError。其中Global和Math这两个对象又被称为“内置对象”,这两个对象在脚本程序初始化时被创建,不必实例化这两个对象。

宿主对象

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

自定义对象

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

第八题

在这里插入图片描述
解析:

在这里插入图片描述

第九题

在这里插入图片描述
解析:

静态语言(强类型语言)

静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型。
例如:C++、Java、Delphi、C#等。

动态语言(弱类型语言)

动态语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。
例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。

猜你喜欢

转载自blog.csdn.net/weixin_48242257/article/details/121396089