javascript知识点——基础+大厂笔试题

变量声明

变量的声明与赋值是需要分解开的。
变量的声明使用单一的var即可。

变量的命名规则

  1. 变量名必须以英文字母、_、$开头
  2. 变量名可以包括英文字母、_、数字
  3. 不可以用系统的关键字、保留字作为变量名

值类型

js中的值类型也就是数据类型,分为不可改变的原始值(栈数据)和引用值(堆数据)

原始值

number string boolean undefined null

引用值

array object function date regexp

区别
原始值是存放到栈里面,栈的特点是先入后出。
引用值是存放在堆里面,堆里面存放的是内容,栈里面存放的是堆的地址。

斐波那契数列

var n = parseInt(window.prompt('input'));
var first =1,second=1,third;
if(n>2){
	for(var i=0;i<n-2;i++){
		third=first+second;
		first=second;
		second=third;
	}
	document.write(third);
}else{
	document.write(1);
}

求100以内的所有的质数

var count=0;
for(var i=1;i<100;i++){
	for(var j=1;j<=i;j++){
		if(i%j==0){
			count++;
		}
		if(count==2){
			document.write(i+" ");
		}
		count=0;
	}
}

break与continue

break只能是放到循环语句中,如果放到别的地方,就会报错
continue是停止本次循环,进行下次循环

编程的两种形式

面向过程和面向对象

函数声明的三种方式

function 函数名(){}
var 变量=function 函数名(){}  //命名函数表达式
var 变量=function(){}   //此函数为匿名函数表达式

函数形参与实参

形参的个数可以超过实参
没有赋值的形参是undefined
形参的个数可以小于实参
形参都放在arguments中

形参的个数:arguments.length
实参的个数:函数名.length

当形参和实参个数相同的时候
则实参和arguments相映射,一一对应,你变我也变

但是当个数不相同的时候,特别是实参个数少于形参的时候,则不会改变没有形参参数的数值

获取字符串的每一位的两种方式

str[0] str.charAt(0)

字符串反转:123转为仨俩壹

function reverse(){
	var num = window.promt('input');
	var str="";
	for(var i=num.length-1;i>=0;i--){
		str+=transer(num[i]);
	}
	document.write(str);
}
function transfer(target){
	switch(target){
		case "1":
		return '壹';
		case "2":
		return '俩';
		case "3":
		return "仨";
	}
}

解题思路:
输入数字成为字符串,通过字符串的遍历进行逆序,然后通过一个转化为汉字的函数进行转化。

利用递归写阶乘函数

function jc(n){
	if(n == 1){
		return 1;
	}
	return n*jc(n-1);
}

使用递归需要注意两点:

  1. 找规律;
  2. 找出口;

利用递归写斐波那契数列

function fb(n){
	if(n==1||n==2){
	return 1;
	}
	return fb(n-1)+fb(n-2);
}

js运行三部曲

  1. 语法分析
  2. 预编译
  3. 解释执行

预编译

函数声明整体提升,变量 声明提升

** imply global 暗示全局变量: ** 即任何变量,如果变量未经声明就赋值,此变量就为全局对象所有。
** 一切声明的全局变量,都是window的属性 **。
预编译的四部曲:

  1. 创建AO对象
  2. 找形参和变量声明,将变量和形参名作为AO属性名,值为Undefined
  3. 将实参值和形参相统一
  4. 在函数体里面找函数声明,值赋予函数体

任何执行期上下文中的this都指向的是window,通过New关键字的方式,可以进行构造函数创建对象,改变this指向,this最终指向的是创建的对象。

for循环中出现闭包的情况

如果在for循环中,对每一个元素都绑定一个函数的话,则会形成闭包

function test(){
var arr = [];
for(var i=0;i<10;i++){
	arr[i]=function(){
		console.log(i);
	}
}
return arr;
}

解决for循环中的闭包问题的方法就是使用立即执行函数

function test(){
var arr=[];
for(var i=0;i<10;i++){
	(function(j){
		arr[j]=function(){
			console.log(j);
		}
	})(i)
}
}

几道大厂前端笔试题

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

2015年阿里笔试题

function test(){
	var liCollection = document.getElementsByTagName('li');
	for(var i=0;i<liCollection.length;i++){
		(function(j){
			liCollection[j].onclick=function(){
				console.log(j);
			}
		}(i))
	}
}

** 利用立即执行函数解决for循环中的闭包问题 **

写一个方法,求一个字符串的字节长度

在这里插入图片描述

function retByteslen(target){
	var count = target.length;
	for(var i=0;i<target.length;i++){
		if(target.charCodeAt(i)>255){
			count ++;
		}
	}
}

** 解题思路: **汉字的字符比英文的字符多1个;
提取变量后可以如下编写函数:
在这里插入图片描述

构造函数的内部原理

  1. 在函数体最前面隐式的加上this={}
  2. 执行 this.xxx=xxx;
  3. 隐式的返回this

原型

  1. 定义:原型是function 对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。
  2. 利用原型的特点和概念,可以提取共有属性。
  3. 对象如何查看原型,可以通过 proto
  4. 对象如何查看对象的构造函数 constructor
  5. 构造函数有个自带的属性叫prototype,也就是原型,是一个对象。

构造函数的最终级别的原型就是 Object.prototype
绝大多数的对象最终都会继承自Object.prototype,也有可能是Null;

创建对象的方式可以是:Object.create(原型);

创建对象的两种方式

var obj={};//通过对象字面量的方式进行创建
var obj1=new Object();

js有精度问题,所以一般都不处理数据

call/apply

作用:改变this指向
区别:后面传的参数形式不同
第一个参数都是改变后的this,如果传的是null,则不改变this指向
call后面的参数是一个个进行传递的,apply后面的参数是一个arguments数组

继承的问题

function inherit(Target,Origin){
	function F(){};
	F.prototype=Father.prototype;
	Son.prototype=new F();
}
Father.prototype.lastName="Deng";
function Father(){};
function Son(){};

通过中间变量的形式可以解决共用原型链的问题

通过中间变量解决共用原型链的模式叫:“圣杯模式”;

圣杯模式(解决共用原型的问题)

function inherit(Target,Origin){
	function F(){};
	F.prototype=Origin.prototype;
	Target.prototype=new F();
	Target.prototype.constructor=Target;
	Target.prototype.uber=Origin.prototype;
}
Father.prototype.lastName='Deng';
function Father(){}
function Son(){}
inherit(Son,Father);
var son = new Son();
var father = new Father();

命名空间

管理变量,防止污染全局,适用于模块发开发
利用闭包实现变量私有化,可以实现命名空间,防止变量污染

原生javascript实现仿jquery链式调用

var deng = {
	smoke:function(){
		console.log('smoking');
		return this;
	},
	dirnk:function(){
		console.log('dirnking');
		return this;
	},
	perm:function(){
		console.log('preming');
		return this;
	}
}
deng.smoke().dirnk();

通过return this的方式,可以保证每个函数都可以返回自身对象,所以都可以链式调用的。

对象的枚举

for in
hasOwnProperty这个是对象原型链上的判断属性是不是它自己的一个方法
in 判断这个属性名是不是当前对象的,如果是对象原型上面的,也会返回true的
instanceof A instanceof BA对象是不是B构造函数构造出来的 等同于 A对象的原型链上有没有B的原型

判断对象和数组的三种方法

可以通过Instanceof进行数组和对象的判断

[] instanceof Array 结果是true;
{} instanceof Array 结果是false;

可以通过constructor进行数组和对象的判断

[].contructor结果是Array;
{}.constructor的结果是Object;

可以通过toString()方法进行数组和对象的判断

Object.prototype.toString.call([]) 结果是 “[object Array]”;
Object.prototype.toString.call({}) 结果是“[object Object]”;
Object.prototype.toString.call(123) 结果是"[object Number]"

this

  1. 函数预编译过程中 this指向的是window
  2. 全局作用域里 this指向的是window
  3. call/apply可以改变函数运行时的this指向
  4. obj.func() func()里面的this指向obj

callee与caller

立即执行函数,执行完成后,函数会销毁,所以此时可以通过arguments.callee的方式进行调用递归函数

var num = (function (n){
if(n==1){
	return 1;
}
return n * 阶乘(n-1);//此时的阶乘可以用  arguments.callee(n-1);来代替
}(100))
function test(){
	demo();
}
function demo(){
	console.log(demo.caller);
}
test();

深度克隆

function deepClone(origin,target){
var target = target || {},
	toStr = object.prototype.toString,
	arrStr="[object Array]";
	for(var prop in origin){
		if(origin[prop] !== "null" && typeof(origin[prop])=="object"){
			target[prop]=toStr.call(origin[prop])==arrStr?[]:{};
			deepClone(origin[prop],target[prop]);
		}else{
			target[prop]=origin[prop];
		}
	}
	return target;
}

自己写一个push方法

var arr = [1,2,3];
Array.prototype.push=function(){
	for(var i =0;i<arguments.lengthd;i++){
		this[this.length]=arguments[i];
	}
	return this.length;
}

数组的几个方法

push是可以在数组的最后一位进行添加,可以添加多个参数。
pop是可以把数组的最后一位剪切出去,传递参数也是没有用的,只会截取最后一位。
unshift是在数组的前面进行添加,可以传递参数,也可以传递多个参数。
shift是在数组的前面进行删除,传递参数也是没有用的。
slice是数组的截取方法,是从第一个参数位开始截取,截取到第二个参数位为止。如果只有一个参数的话,则截取到数组的最后一位。
sort是进行数组的排序,最终会改变原数组。此处的排序不会完全按照数字大小进行排序,是ASCII码。
splice是截取,有三部分参数,第一个参数是从第几位开始,第二个参数是截取多少的长度,第三个以及后面的参数是在数组切口处添加的新的数据。

自己写一个splice方法

splice = function (pos){
	pos += pos>0?0:this.length;
}

自己写一个sort方法

arr.sort(function(a,b){
	return b-a;//降序排列
	return a-b;//升序排列
})

给一个有序数组乱序

arr.sort(function(a,b){
	return Math.random()-0.5;
})

按照字符串的长度进行排序

var arr = ['ad','ddd','ddddd']
arr.sort(function(a,b){
	return a.length-b.length;//升序
});
for(var i=0;i<arr.length;i++){
	for(var j=0;j<i;j++){
		arr.sort(function(i,j){
			return i.length - j.length;
		})
	}
}

按照字符串的字节长度进行排序

function retBytes(str){
	var num = str.length;
	for(var i=0;i<str.length;i++){
		if(str.charCodeAt(i) > 255){
			num ++;
		}
		return num;
	}
}
var arr =['asdf','ddd','adgdasg'];
arr.sort(function(a,b){
	return retBytes(a) - retBytes(b);
})

包装type函数

function type(target){
	var template = {
		"[object Array]":"array",
		"[object Object]":'object',
		"[object Number]":'numer - object',
		"[object Boolean]":'boolean - object',
		"[object String]":'string - object'
	}
	if(target === null){
		return "null";
	}
	if(typeof (target) == "object"){
		var str = Object.prototype.toString.call(target);
		return template[str];
	}else{
		return typeof(target);
	}else{
		return ret;
	}
}

在数组原型上面添加一个数组去重的方法

Array.prototype.unique=function(){
	var temp={},
		arr=[],
		len=this.length;
	for(var i=0;i<len;i++){
		if(!temp[this[i]]){
			temp[this[i]] = "abc";
			arr.push(this[i]);
		}
	}
	return arr;
}

str.split(“”)

字符串打散成数组

事件委托

var ul = document.getElementsByTagName('ul')[0];
ul.onmouseover = function (e){
	var event = e|| window.event;
	var target = event.target || event.srcElement;
	target.style.backgroundColor="rgba(0,255,)"+target.getAttribute('img-date')+")";
	target.setAttribute('img-date',parseInt(target.getAttribute('img-date'))+6);
}

元素的鼠标滑过事件,event target这两个参数兼容性的处理,e.target元素获取属性的方式是:
target.getAttribute('css属性'),设置元素的属性:target.setAttribute('css属性',parsetInt(target.getAttribute('css属性')));

创建一个div并添加到body中(原生Js)

var newDiv = document.createElement('div');
document.body.appendChild(newDiv);

封装一个获取元素子节点的方法

var div = document.getElementsByTagName('div')[0];
function retElementChild(node){
	var temp = {
		length:0,
		push:Array.prototype.push,
		splice:Array.prototype.splice
	},
	child = node.childNodes,
	len = child.length;
	for(var i=0;i<len;i++){
		if(child[i].nodeType === 1){
			temp.push(child[i]);
		}
	}
	return temp;
}
  • 9
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叶浩成520

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值