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,'.'));