经典面试题集合

1.考察闭包  (看似考察绑定事件addEventListener,实际考察闭包)

     题目 给页面多个li绑定点击事件 并打印顺序

//题目 给页面多个li绑定点击事件 并打印顺序


var liArr = document.querySelectorAll('li');
// console.log(liArr);

// 法一,用[].forEach.call  无需用到闭包
[].forEach.call(liArr,function(ele,index){
	ele.addEventListener('click',function(){
		console.log(index);
	})
})
// 
// 
// 
// 法二  闭包  将i保存到j的作用域中 避免所有i都指向同一个作用域  
for (var i = 0; i < liArr.length; i++) {
	(function(j){
		liArr[j].addEventListener('click',function(){
			console.log(j);
		})
	}(i))
}

2. 写一个计算字符串总共字符数的函数(重在扩展思路)

// 写一个计算一个字符串内字节数的函数 重在思路
	// 所需方法 str.charCodeAt(索引); 返回索引值处字符的unicode编码。
	// 思路一 分别对英数字  汉字做处理
	function setBytesLen(str){
		var count = 0;//存放字节数
		for (var i = 0; i < str.length; i++) {
			if(str.charCodeAt(i) > 255){//大于255为两个字节
				count += 2;
			}else{//<=255为英文字符 一个字节
				count ++;
			}
		}
		console.log(count);//所有字节
	}

	// 思路二  英数字字节为1 汉字为2 则基础字节都为1 在遇到汉字时+1即可
	function setBytesLen(str){
		var count,
			len;
			count = len = str.length;//str.length每次都是点语法计算,可以将length保存使用
		for (var i = 0; i < len; i++) {
			if(str.charCodeAt(i) > 255){//大于255为两个字节
				count ++;
			}
		}
		console.log(count);//所有字节
	}

3. 逗号计算符

	// 逗号计算符
	var a = (1,2);//打印a  为2
	// 先计算,前面的,依次计算,取最后的
	var a = (
			function a(){
				return '1';
			},
			function b(){
				return 2;
			}
		)();
	console.log(typeof a);
	// 解析:依次执行()内的,取最后的,相当于
	// var a = function b(){return 2;}  a();所以打印a的type为number

4. 数字类型加字符串类型 为字符串类型

var x = 1;
if (function f(){}) {
	x+=typeof f;
}
console.log(x);//1undefined
// 解析:	x=1; typeof f为undefined  typeof typeof f为string类型
// x+typeof f  即为x+‘undefined’   数字加字符串 为字符串 即1undefined

5.考察包装类  原始值没有属性(简单num string类型)

var str = 'abc';
str+=1;
var test = typeof(str);
if (test.length==6) {
	test.sign = 'typeof返回结果为string';
}
console.log(test.sign);

// 答案:打印出undefined
// 解析:
// str+=1; str = 'abc1',为string类型。
// test='string';  test.length系统自动new String获取到length为6
// test.sign=''; 由于test为string类型,没有属性。系统new String().sign了之后立刻删除
// 再次打印test.sign时 系统new String(test).sign  此时的sign没有赋值,为undefined

6.考察心细了  题目简单

答案:A  参数没传进去哈

7.考察对象、闭包

答案:1 2 1 

8.考察函数提升

// 代码执行完后 xyz分别是多少
var x = 1,y = z = 0;
function add(n){
	return n = n+1;
}
y=add(x);

function add(n){
	return n = n +3;
}
z=add(x);

console.log(x);
console.log(y);
console.log(z);
// 答案:1 4 4
// 解析:很简单  两个add()函数,在函数声明提升时后面的add覆盖前面的add
// 执行的add都是最下面的add()函数

9. 考察实参、跟函数执行方式

// 下列选项能打印出1,2,3,4,5的是
// A
function foo(x){
	console.log(arguments);
	return x;
}
foo(1,2,3,4,5);

// B
function foo(x){
	console.log(arguments);
	return x;
}(1,2,3,4,5)

// C
(function foo(x){
	console.log(arguments);
	return x;
})(1,2,3,4,5)

// 答案:A C
// 解析:A里面打印的是实参,foo传参为实参12345所以正确
// 		 B不会报错也不会执行,不是正确的函数调用方式,系统会将函数体跟后面的()分开来解读
// 		 C为立即执行函数 跟A一样的 只是调用方式不一样

10.考察parseInt 进制

答案:3,NAN,NAN或者3,NAN,3 有的浏览器认为0进制报错 有的浏览器认为0进制就是没有进制

11.考察typeof类型

答案:string  object

解析:没有array  null也是object

12.考察arguments修改实参 

// 下面b打印什么结果
function b(x,y,a){
	arguments[2] = 10;
	console.log(a);
}
b(1,2,3);


// 下面b又打印什么结果
function b(x,y,a){
	a = 10;
	console.log(a);//10
	console.log(arguments[2]);//10
}
b(1,2,3);

// 答案:都是10
// 解析:arguments[2]修改就是修改了a  两者任何一方修改另一方也修改
// 		 下面的a修改为10  实参的a也会被修改为10

13.考察运算符

答案:1  换行  1   

解析:打印a++   是先打印a  打印完后再a+1  打印--b是直接打印b——1后结果

 

14. 求一些数学运算  方程

// 求2的n次幂   用循环求
var n = prompt('n');
var result = 2;
for (var i = 1; i < n; i++) {
	result *=2 ;
}
console.log(result);


// // 阶乘  用循环求
// 2!=2*1    3!=3*2*1
var n = prompt('n');
var i = n-1;
while(i>0){
	n*=i;
	i--;
}


// 斐波那契  用循环求
// n位  f    c    t 
//      1    1    2    3
// 		  f    c    t
var n = prompt();  
var first = 1,
	second = 1,
	third = 1;
	for (var i = 0; i < n - 2; i++) {
			third = first + second;
			first = second;
			second = third;
	}
	document.write(third);

15. 打印1-100的质数  这个思路很美好了

// 打印出1-100的质数  这个思路可以啊  以前老师可把我说晕了
// 质数定义:除1和自身外,不能被其他数整除  也就是说1-自身之间只能被整除两次
var count = 0;//定义变量来记录整除的次数
for (var i = 0; i < 100; i++) {
	// 1-100之间的被除数
	for (var j = 0; j <= i; j++) {
		// 1-自身之间的除数
		if (i%j == 0) {
			count++;//如果被整除了就记录一次  如果到最后只有两次证明是质数
		}
		if (i==j && count==2) {
			// i == j  已经除到自身来了  而count==2 只整除两次 则为质数
			document.write(i + " ");
		}
	}
	count = 0;//将记数重置为0  继续下一个数的判断
}

16:考查水平垂直居中

// 一行文本  需要水平和垂直居中

// 法一
// 1.text-align:center;水平居中  line-height:等于height;垂直居中

// 法二
// 1.给盒子display:flex;
// 2.align-items: center;垂直居中   justify-content:space-around;水平居中

17. 考查进制 parseInt(数字,基底进制) 转为10进制

进制:到了进制的位数,就让个位变为0 十位为1
二进制 1 10(2) 满2就进位为10  10代表2   11代表3 2+1
            二进制中  100 = 2*2=4   解析:1 10 11 (11+1进位100 也就是4)
        规律:1 = 1 
              10 = 2
              100 = 2^2 = 4
              1000 = 2^3 = 8
              10000 = 2^4 = 16    
              所以:1111 = 2^3 + 2^2 + 2 + 1 = 15 
十进制 1 2 3 4 5 6 7 8 9 满9加1时 为10  10是一个十位数
十一进制 1 2 3 4 5 6 7 8 9 a(代表10) 未满11,所以这里的10是一个个位数用a来表示
            a+1=10  这里的10在十一进制代表11
十六进制 1 2 3 4 5 6 7 8 9 a(10) b(11) c(12) d(13) e(14) f(15) 10(代表16)
    十六进制中  1f就是10+f  也就等于16+15=31
    十六进制中 19 = 16+9 = 25

笔试题
请问一下表达式的结果是什么?
A  parseInt(3,8)  理解题目:以8进制为基底,将8进制的3转化为10进制
B  parseInt(3,2)  以8进制为基底,将8进制的3转化为10进制
C  parseInt(3,0)  以8进制为基底,将8进制的3转化为10进制

解析:A:3    8进制的3就是3 转为10进制还是3
         B:NAN   2进制中没有3
         C:NAN/3 0进制是个异常进制 结果可能是3 也可能是NAN

 

18.考查类型

 以下哪些是javascript语言typeof返回的结果
 string(正确)
 array(错误,array是object)  
 object(正确)   
 null(错误,null也是object)

typeof '12';//string
typeof 12;//number
typeof [];//object
typeof {};//object
typeof null;//object
typeof undefined;//undefined

19.call跟apply

 call跟apply的区别
 call跟apply都是改变this指向,但两者的传参列表不一样

20.考察形参实参 arguments

// 看看下面alert的结果是什么
function b(x,y,a){
	arguments[2] = 10;
	alert(a);
}
b(1,2,3);

// 答案:10
// 解析:arguments[2] = 10;就是将形参的a改为10 所以alert10

// 如果函数体改成下面,结果又会是什么?
function b(x,y,a){
	a = 10;
	alert(arguments[2]);
}
b(1,2,3);
// 答案:10
// 解析:a = 10;也就是把arguments[2] = 10;

21.考察逗号运算符   (1,2)

// 问:下面typeof f的类型是什么

var f = (

		function a(){
			return 1;
		},
		function b(){
			return '1';
		}

	)();
typeof f;

// 答案:string
// 解析:这里考察到了一个运算符号,逗号。
		// var num = (1,2);num将会为2 ,会赋值为最后一个值
		// 所以f的()中,会取最后的b()函数,然后执行。返回字符串1

22. 考察运算符 跟if条件

// 下列程序执行打印的结果
var x = 1;
if (function f(){}) {
    x += typeof f;
}
console.log(x);

// 答案:x为1undefined
// 解析:if中的条件表达式为true,function f(){}为true
//         但f本身是未定义,所以typeof f为undefined
//         x+=undefined    就是1+undefined  typeof undefined是字符串类型,
//         1+字符串的undefined 就是1undefined

23.考察isNaN  parseInt


// 问下列为true的是
// A.
	undefined == null;
// B
	undefined === null;
// C
	isNaN('100');
// D
	parseInt('1a')==1;

	答案:A D
	解析:AB:undefined与null相等,不全等
		  C:isNaN()在内部先转为Number,如果是NaN则为true,否则false
		  D:parseInt('1a');取整数部分,取到非数字位终止
由isNaN()衍生一个小练习,自己封装一个isNan函数


function isNaN(num){
	// 由于NaN不等于也不全等于NaN
	// 所以if里面不能直接用Number()与NaN做判断
	// 先转为字符串类型,再对比
	if(Number(num).toString()=='NaN'){
		return true;
	}else{
		return false;
	}
}

24. 引用类型值得比较

25.考察this

 

var name = '222';
var a = {
	name : '111',
	say : function(){
		console.log(this.name);
	}
}
var fun = a.say;
fun();
a.say();
var b = {
	name : '333',
	say : function(fun){
		fun();
	}
}
b.say(a.say);
b.say = a.say;
b.say();



答案:222 111 222 333
解析:
	var fun = a.say;//就是fun现在就是a.say的函数体,与引用地址无关
	fun();//在全局执行fun();这时的this就是window,所以打印出222

	a.say();//就是a调用自己的say()函数,this就是a自己,所以打印出111

	b.say(a.say);//将a.say的函数体传参给b.say并执行。
				// 只是在b的say中执行函数体,没有调用者,所以this为window。
				// 相当于预编译的this
	b.say = a.say;//将b.say的函数体改成a.say的函数体。此时b.say就成了
	var b = {
		name : '333',
		say : function(){
			console.log(this.name);
		}
	}
	b.say();//执行b.say(),自然打印的是333



//关于this的知识点
1.在预编译时this指向window
2.在全局作用域里this指向window
3.apply/call可以改变this指向
4.obj.fun();fun里面的this指向obj 谁调用指向谁

function test(c){
	var a = 123;
	function b(){

	}
}

// 执行前预编译
AO{
	this : window,//预编译时的this指向window
	arguments : [2],//有实参列表
	c : 2,
	a : 123,
	b : function(){}
}

test(2);

var obj = {
	test : function(){
		console.log(this);//this指向obj
	}
}

obj.test();

26.考察this

var foo = '123';
function print(){
	var foo = '456';
	this.foo = '789';
	console.log(foo);
}
print();

// 答案:456
// 解析:全局中的foo为123
	  // 函数内部foo为456
	  // this.foo=789;这里的this是window,所以全局中的foo改为789
	  // 函数内部打印foo,先找内部的foo,为456.所以打印456

var foo = '123';
function print(){
	this.foo = '789';
	console.log(foo);
}
new print();

// 答案:123
// 解析:全局中的foo为123
// 	new print()时执行函数,
// 	由于有new,所以相当于var this = Object.create(print.prototype);
// 	这时的this.foo=789就是给原型添加foo为789.
// 	打印foo,new print中没有foo,只有this.foo。所以打印的是全局中的foo123

27.考察this跟new fun()

// 运行test()跟new test()的结果分别是什么?
var a = 5;
function test(){
	a = 0;
	alert(a);
	alert(this.a);
	var a;
	alert(a);
}
test();
new test();


答案:test();-->0 5 0
	  new test():-->0 undefined 0
解析:test()的情况:
		全局中a=5;
		在test内部提升变量名a,然后赋值a=0。所以内部a=0
		alert(a);为内部的a  0;
		alert(this.a);这里的this是window。所以是全局的a 5
		下面的alert(a)同理为内部的a  0
	  new test()的情况:
	  	全局中a=5。
	  	new后,有了隐性var this = Object.create(test.prototype);
	  	依旧提升变量名a,然后赋值a=0。所以内部a=0
	  	alert(a);为内部的a  0;
	  	alert(this.a);这里的this是test.prototype。而原型上没有a。所以undefined
		下面的alert(a)同理为内部的a  0

28.考察函数内部变量提升、执行顺序等

// 下列执行结果
function print(){
	console.log(foo);
	var foo = 2;
	console.log(foo);
	console.log(hello);
}
print();

答案:undefined 2 报错
解析:	function print(){
			//1、 print内部提升变量声明foo
			console.log(foo);//2、此时定义了foo,但是未赋值。所以undefined
			var foo = 2;//3、此时赋值
			console.log(foo);//foo为2
			console.log(hello);//没有定义hello,报错
		}

29.考察预编译

function print(){
	var test;
	test();
	function test(){
		console.log(1);
	}
}
print();

答案:1
解析:在print执行前  预编译过程
		AO{
			找到变量名 赋值undefined
			test:undefined;
			找到函数名赋值函数体 函数名也是test,覆盖前面的undefined
			test:function test(){
					console.log(1);
				}
		}
		执行时,test();打印出1
		也就是无论在函数定义前后执行函数都可以

30.考察this指向跟bind

function print(){
	var marty = {
		name : 'marty',
		printName : function(){
			console.log(this.name);
		}
	};
	var test1 = {name :'test1'};
	var test2 = {name :'test2'};
	var test3 = {name :'test3'};
	test3.printName = marty.printName;
	var printName2 = marty.printName2.bind({name:123});


	marty.printName.call(test1);
	marty.printName.apply(test2);
	marty.printName();
	printName2();
	test3.printName();

}
print();


// 答案:test1  test2 marty test3
// 解析:  暂时忽略bind

function print(){
	var marty = {
		name : 'marty',
		printName : function(){
			console.log(this.name);
		}
	};
	var test1 = {name :'test1'};
	var test2 = {name :'test2'};
	var test3 = {name :'test3'};
	test3.printName = marty.printName;
	// 此时的test3为下
	// test3 : {
	// 		name : 'test3',
	//      printName : function(){
	//    		console.log(this.name);
	//    	}
	// }
	// var printName2 = marty.printName2.bind({name:123});


	marty.printName.call(test1);//改变了marty.printName的this 打印test1
	marty.printName.apply(test2);//打印test2
	marty.printName();//打印marty
	// printName2();
	test3.printName();//打印test3

}

31.考察引用值修改跟原型链

var bar = {a:'002'};
function print(){
	bar.a = 'a';
	Object.prototype.b = 'b';
	return function inner(){
		console.log(bar.a);
		console.log(bar.b);
	}
}
print()();

//答案:a  b
//解析:超简单啊。就是bar.a改为了a  在Object的原型上加了b = b
//			虽然bar自身没有b,但是由于bar是个json,会继承Object的原型。所以有b

32. 考察sort排序

// 题:给一个有序的数组,将他随机乱序。
var arr = [1,2,3,4,5,6,7];

	arr.sort(function(){
		return Math.random() - 0.5;
	})
	
// 解析:由于sort(function(){})内是要进行多伦对比,
// 		 每次对比都要返回一个正数或者负数来决定排序。
// 		 可以用Math.random()  0-1之间的随机数来觉得随机的正负数
// 		 Math.random() - 0.5 就是随机的正负数
// 		 这样一来就会随机排序
// 题: 给下面数组,按照数组内对象的年龄大小排序
	var deng = {
		name : 'deng',
		age : 52,
		sex : 'male'
	};
	var zhang = {
		name : 'zhang',
		age : 20,
		sex : 'male'
	};
	var cheng = {
		name : 'cheng',
		age : 34,
		sex : 'male'
	};

	var people = [deng,zhang,cheng];
//直接比较age 如下
	people.sort(function(a,b){
		return a.age - b.age;
	})
	// 题:将数组内的值按长度排序
	var arr = ['a','asdd','s','gefedsfsf','sadadsa'];
	// 同理 只需要对length做比较
		 arr.sort(function(a,b){
			return a.length - b.length;
		})
	// 题:将数组内的值按长度排序
	var arr = ['a','asdd','s','gefedsfsf','sadadsa'];
	// 同理 只需要对length做比较
		 arr.sort(function(a,b){
			return a.length - b.length;
		})

	// 题:将数组内的值按字节长度排序
	var arr = ['我是','123','嘿嘿嘿12','123554','你好撒23dd'];

	// 思路:先封装一个求字节长度的函数
	function retBytes(str){
		var num = str.length;
		for (var i = 0; i < str.length; i++) {
			if (str.charCodeAt(i)>255) {
				num++;
			}
		}
		return num;
	}
	// 然后用sort排序
	arr.sort(function(a,b){
		return retBytes(a) - retBytes(b);
	})

33.考察私有化变量

// 面试题 考察私有化变量
function Person(name,age,sex){
	var a = 0;
	this.name = name;
	this.age = age;
	this.sex = sex;
	function sss(){
		a++;
		document.write(a);
	}
	this.say = sss;
}
var oPerson = new Person();
oPerson.say();
oPerson.say();
var oPerson1 = new Person();
oPerson1.say();

// 答案:1 2 1
// 解析:实例化oPerson时,oPerson为:
// oPerson{
// 		say = function sss(){
// 			a++;
// 			document.write(a);
// 		}
// 		私有化变量a保存在say函数中。为0
// }
// 当第一次oPerson.say();打印a为1
// 第二次oPerson.say()中的a还是同一个a(1),++后打印为2
// 当实例化oPerson1时,oPerson1是新的对象。保存在say中的a为0.所以打印为1

34.考察数组与对象的特性 优化代码

// 尝试优化一下代码  使代码看起来更优雅
// 法一:用对象
function getDay(day){
	var temp = {
		1:"Monday",
		2:"Tuesday",
		3:"Wednesday",
		4:"Thursday",
		5:"firday",
		6:"Thursday",
	};
	if (temp[day] == undefined) {
		document.write('error');
	}else{
		document.write(temp[day]);
	}
}
// 法二:用数组
function getDay1(day){
	var temp = ["Monday","Tuesday","Wednesday","Thursday","firday","Thursday"];
	var ret = temp[day-1];
	if (ret == undefined) {
		document.write('error');
	}else{
		document.write(ret);
	}
}

35、考察封装深度克隆

// 实现object的clone方法
function deepClone(origin,target){
		
	for(var prop in origin){
		var type = typeof origin[prop];
		if (type == 'object') {
			// 引用类型深度克隆
			var ret = Object.prototype.toString.call(origin[prop]);
			if (ret == '[object Array]') {
				// 数组类型
				target[prop] = [];
			}else{
				// object类型
				target[prop] = {};
			}
			// 用递归再次克隆
			deepClone(origin[prop],target[prop]);
		}else{
			// 简单类型 直接克隆
			target[prop] = origin[prop];
		}
	}
}

36、考察对象的继承

// 选一种你熟悉的方式实现js对象的继承  
// 圣杯模式
function inherit(Origin,Target){
	function F(){}
	F.prototype = Origin.prototype;
	Target.prototype = new F();
	Target.prototype.constructor = Target;	
}

37、考察函数表达式声明

// 3、考察函数表达式声明
// 问:typeof a ();返回什么类型
var h = function a(){
	return 23;
};
typeof a();


// 答案:语法执行会报错  a is not defined
// 解析:var h = function a(){};
// 当前面有了函数表达式var h;那么后面的函数名a就会被删去,不存在。
// 所以当typeof a()时已经没有a这个函数了、报错

38、考察delete

(function(x){
	delete x;
	return x;
}(1))


// 答案:1
// 解析:delete无法删除掉x

 

39、考察typeof

// 2、考察typeof
function test(){
	console.log(typeof arguments);//object
}
test();

40、考察div布局 垂直水平居中

 给一个div 宽高均400 背景色 边框 在页面居中

 法一:
   .box {
    	width: 400px;
    	height: 400px;
    	margin: auto;
    	position: absolute;
    	left: 0;
    	right: 0;
    	top: 0;
    	bottom: 0;
}

法二:  
 .box {
    	width: 400px;
    	height: 400px;
        position: absolute;
    	top: 50%;
    	left: 50%;
    	margin-left:-200px;
    	margin-top:-200px;
}

41、考察利用对象去重

    题目:字符串去重

// 字符串去重
//思路:将字符串的每一个字符放进新对象中作为属性,如果存在这个就不放。不存在的时候就放,并且用新的字符串来接收。


var str = 'dsafdggfdgfasdfdijfwdhjdhfjdhjfdhjhdfhdkq';
var obj = {};
var newstr = '';
for (var i = 0; i < str.length; i++) {
	if (!obj[str.charAt(i)]) {
		obj[str.charAt(i)] = '1';
		newstr += str.charAt(i);
	}
}

42、一个字符串[a-z]组成,找出其中第一个只出现了一次的字母

// 一个字符串[a-z]组成,找出其中第一个只出现了一次的字母
// 思路:将字符串的每一个字符放入新对象作为属性,第一次出现的时候就令值为1,
// 之后每一次出现就++。最后遍历对象,找到第一个值为1的属性。也就是只出现了一次的。
var str = 'dsafdggfdgfasdfdijfwdhjdhfjdhjfdhjhdfhdkq';
var obj = {};
for (var i = 0; i < str.length; i++) {
	if (obj[str.charAt(i)]) {
		obj[str.charAt(i)]++;
	}else{
		obj[str.charAt(i)] = 1;
	}
}
for(var k in obj){
	if (obj[k] == 1) {
		console.log(k);
		break;
	}
}

43.封装insertAfter  类似于insertBefore

	<div class="wrap">
		<div id="div1">1</div>
		<div id="div2">2</div>
		<div id="div3">3</div>
	</div>

 



<script>


// 封装函数insertAfter()   功能类似于insertBefore()
// 如:在wrap里有三个div。我要插入一个 在某个div的后面
var wrap = document.getElementsByClassName('wrap')[0];//先获取到父盒子
var div1 = document.getElementById('div1');
var div2 = document.getElementById('div2');
var div3 = document.getElementById('div3');

// 创建一个div4
var div4 = document.createElement('div');
	div4.innerHTML = '我是新的';

// insertBefore
wrap.insertBefore(div4,div1);//父盒子.insertBefore(插入元素,某个相对照元素)

// 封装insertAfter()
Element.prototype.insertAfter = function(newEl,old){
	var nextEl = old.nextElementSibling;
	// 判断后面是否还有兄弟节点
	if (nextEl) {
		// 有 则用insertBefore放在兄弟节点前面
		this.insertBefore(newEl,nextEl);
	}else{
    // 	后面没有兄弟节点的话  就直接放在父盒子最后  appendChild
		this.append(newEl);
	}
}


wrap.insertAfter(div4,div3);

44.考察创建节点 文本节点 元素节点
 



// 请写一段javascript脚本生成下面这段DOM结构。要求:使用标准的DOM方法或属性
// <div class='example'>
// 	<p class='slogan'>good</p>
// </div>

var div = document.createElement('div');
var p = document.createElement('p');
	div.setAttribute('class','example');
	p.setAttribute('class','slogan');
	var text = document.createTextNode('good');
	div.append(p);
	p.append(text);
	document.body.append(div);


// 直接的方法
	div.innerHTML = '<p class="example">good<p/>';




45.将dom结构逆序 改变顺序  考察append  appendChild

// 将下面的结构逆序  使中间的div顺序为321
	// <div class="wrap">
	// 	<div id="div1">1</div>
	// 	<div id="div2">2</div>
	// 	<div id="div3">3</div>
	// </div>
// 思路:用appendChild  相当于一个剪切功能
var wrap = document.getElementsByClassName('wrap')[0];//先获取到父盒子
var div1 = document.getElementById('div1');
var div2 = document.getElementById('div2');
var div3 = document.getElementById('div3');
wrap.appendChild(div2);
wrap.append(div1);

46.js原生获取元素计算属性   兼容ie封装 考察window.getComputedStyle()


// 获取元素的计算css属性
// 标准:window.getComputedStyle(ele,null)[prop]
// ie8:ele.currentStyle[prop]
// 

function getStyle(ele){
	if (window.getComputedStyle) {
		return window.getComputedStyle(ele,null);
	}else{
		return ele.currentStyle;
	}
}
console.log(getStyle(div).width);

47. 获取伪类元素的属性  考察window.getComputedStyle(ele,伪元素)

    给div写一个伪元素after   利用计算属性获取伪元素的属性

div {width: 200px;height: 200px;background-color: red;}
div::after {
   content: '';
   display: inline-block;
   width: 50px;height: 50px;background-color: black;
 }
//利用计算属性获取伪元素属性


var div = document.getElementsByTagName('div')[0];
console.log(window.getComputedStyle(div,'after').width);

48.考察递归跟offsetLeft、offsetParent


   		div {width: 200px;height: 200px;background-color: red;border: 1px solid #000;}
		p {width: 100px;height: 100px;background-color: pink;margin: 20px auto;}
	<div>
		<p></p>
	</div>

 


// 利用offset来获取元素距离文档的坐标。
// offsetLeft/Top是元素距离最近定位父级的距离。
// 要求封装一个函数获取元素距离文档的坐标
// 思路:判断元素是否有最近定位父级。依次类推。循环递归
// 

var div = document.getElementsByTagName('p')[0];
var x = 0;
var y = 0;
Element.prototype.getElementPosition = function(){
	console.log(this.offsetParent);
	var parentOff = this.offsetParent;
	if (parentOff.nodeName!='BODY') {
		console.log(1);
		x += this.offsetLeft;
		y += this.offsetTop;
		parentOff.getElementPosition();
	}else{
		console.log(this.offsetParent.nodeName);
		x += this.offsetLeft;
		y += this.offsetTop;
		return {
			'x':x,
			'y':y
		}
	}
}


49.考察正则

// 1.检验一个字符串首尾是否有数字
// \d是数字
var reg = /^\d|\d$/g; //^开头  $结尾  |或
var str = '123abc2';

console.log(reg.test(str));
console.log(str.match(reg));
// 如何匹配出叠词  (字)\1   ()用\1代表复制出第一个()中的元素 一模一样 (b)\1\1\1代表子bbbb
//    /(\w)\1\1\1/  四个括号中匹配出来的相同的字符
// 如:要匹配出 aaaa  这样的四个相同字符格式的字符

var reg2 = /(b)\1\1\1/g; //只能匹配出bbbb
var str2 = 'bbbbccccdddd';
console.log(str2.match(reg2));
var reg3 = /(\w)\1\1\1/g; //能匹配出四个相同的字符 bbbb cccc dddd 1111 AAAA
var str3 = 'bbbbccccdddd1111AAAA';
console.log(str3.match(reg3));

var reg4 = /(\w)\1(\w)\2/g; //能匹配出aabb或者aaaa这种格式 前两位后两位分别相同 \2代表复制第二个()
var str4 = 'aabbccccdddd1111AAAA';
console.log(str4.match(reg4));
// 3.split  把字符串分隔为数组
var reg3 = /a/g;
// var reg3 = /(a)/g;//当加子表达式  分隔后的数组会有子表达式中的字符
var str3 = 'a123a456a789';
console.log(str3.split(reg3));
// 将字符串aabb  转为  bbaa

//如果要将aa bb交换顺序 可以用反向调用子表达式()  符号 $+第几个子表达式 
var reg5 = /(\w)\1(\w)\2/g;
var str5 = 'aabbaabbaabb';
console.log(str5.replace(reg5,'$2$2$1$1'))
console.log(str5.replace(reg5,'$2$1$2$1'))


// 也可以用function来返回替换的新内容
	// str.replace(reg,function(正则返回的值,第一个子表达式,第二个子表达式){})
console.log(str5.replace(reg5,function($,$1,$2){
	return $2+$2+$1+$1+'asasa';

}))
// 将the-first-name 变成the-First-Name
// 思路:用正则找到-f -n  然后替换成大写的F  N
// 		 利用子表达式的反向调用
var reg8 = /-(\w)/g; //匹配到-x
var str8 = 'the-first-name';
// 由于自表达式的反向需要是字符串的格式'$1'。所以要用toUpperCase的话需要function内进行
console.log(str8.replace(reg8,function($,$1){
	return $1.toUpperCase();
}))
//abaaaacab  匹配后面是b的a

// 正向预查  正向断言 ?=x
// 如:要匹配到后面紧跟着b的a
var reg9 = /a(?=b)/g;
var str9 = 'abaaaacab';
console.log(str9.match(reg9)); //匹配出两个a



var reg9 = /a(?!b)/g; //后面不是b的a

// 利用正则对字符aaaaaabbbbbbbbbccccccccc串去重

var str10 = 'aaaaaabbbbbbbbbccccccccc';
var reg10 = /(\w)\1*/g; //\1*代表多个子表达式里的值
// 用replace替换
console.log(str10.replace(reg10,'$1'));
// 1000000000  给数字加点 按国际的格式100.000.000

var str11 = '100000000000';
var reg11 = /(?=(\d{3})+$)/g;
console.log(str11.replace(reg11,'.'));
// 由于会上面的正则只是匹配3位数一个点  所以会出现.100.000  这种情况
var reg12 =  /(?=(\B)(\d{3})+$)/g;//用\B非字边界来区分  如果是不是字的边界处后面有3位数才匹配
console.log(str11.replace(reg12,'.'));


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值