- 1111:“与” 运算符 第一个为布尔值为真直接输出第二个值 第一个为假时,直接输出第一个。如果有三个第四个 一直判断
直到判断为假时输出假的那个数
var a = 2 && 5;
document.write(a);
undefined NaN "" false null 0 这六个值得布尔值为 false
2222: “或” 运算符 碰到真就返回
var num = 0 || 5;
document.write(num);
3333: 条件语句
var score = parseInt(window.prompt('input'));
if(score > 90 && score < 100){
document.write('alibaba');
}
else if(score > 80 && score <= 90 ){
document.write('tencent');
}
else{
document.write('false');
}
4444:循环语句 for , while while语句其实就是for语句简化版 for(;i<10;) = while(i<10)
var i = 0;
for(; i<100 ;i++){
if(i%3==0 || i%5==0 || i%7==0){
document.write(i + " ");
}
}
5555:计算2的n次幂 n可输入并且为自然数
var n = parseInt(window.prompt('input'));
var mul = 1;
for(var i=0;i<n;i++){
mul *=2;
}
document.write(mul);
6666:计算n的阶乘 n可输入
var n = parseInt(window.prompt('input n'));
if(n == 0){
document.write(0);
}else{
var sum = 1;
for(var i=1;i<=n;i++){
sum*=i;
}
document.write(sum);
}
7777"编写一个程序,输入一个三位数的正整数,输出时以反向输出,例:输入123 输出321
var n = parseInt(window.prompt("input n"));
var a = n % 10;
var b = (n-a)/10%10;
var c = ((n-a)/10-b)/10;
var d = a*100 + b*10 +c;
document.write(d);
8888: switch case 语句
var date = window.prompt("input");
switch(date){
case "monday":
document.write("working");
break;
case "tuesday":
document.write("working");
break;
case "wednesday":
document.write("working");
break;
case "thursday":
document.write("working");
break;
case "friday":
document.write("working");
break;
case "saturday":
document.write("relaxing");
break;
case "sunday":
document.write("relaxing");
break;
}
9999: continue 终止本次循环来进行下一次循环
for(var i = 0;i<100;i++){
if(i % 7 == 0){
continue;
}
document.write(i + " ");
}
101010:对象:
var Ashin = {
age:"21",
sex:"man",
education:"doctor",
wife:"ywt"
}
document.write(Ashin.age);
121212: typeof 六种数据类型:
Number:数字
string:字符串
Boolean:布尔类型 ture false
Object:对象 字符串 null(原始值 最初浏览器用来代替空对象的,给对象占位的)
function:函数
undefined:undefined
131313:parseInt用法:
var demo = 17;
var num = parseInt(demo,16);
parseInt(string,radix) 16代表进制 表示把17当作是16进制的数 转化为10进制的数 radix的值只能2-36 parseInt转化为整形 例如"100px"可以转化为100; parseFloat浮点型可以将“100.2px”转化为100.2
document.write(typeof(num) + ":" + num);
141414:toString用法:
var demo = 10;
var num = demo.toString(8);
toString(radix) 可以将一个十进制的数转化为radix进制的数
console.log(num);
151515:toFixed用法
var num = 123.45678;
document.write(num.toFixed(2));
toFixed(Number) 保留几位小数并且四舍五入
161616: 将一个二进制数10010010转化为16进制数:
var demo = 10010010;
var num = parseInt(demo,2);
var ox = num.toString(16);
console.log(ox);
编程:高内聚,弱耦合
171717: 函数:
函数声明:函数命名多个单词拼接在一起时必须首个单词首个字母小写之后的单词首字母要大写,这是编程的习惯
两种函数的定义方式,第二种相当于函数表达式
function theFistName (){
document.write("a");
}
console.log(theFistName);
var test = function (){
document.write("a");
}
181818:函数的参数–形参—实参arguments
function sum(a,b) {
var c = a + b;
document.write(c);
}
sum(1,2);
sum(4,5);
191919:用函数求任意数的加法:
function sum() {
var result = 0;
for(var i = 0;i<arguments.length;i++){
result +=arguments[i];
}
console.log(result);
}
sum(45,48,57,98);
202020:写一个函数 告知你所选定的动物的叫声:
function scream(animal) {
switch(animal){
case "dog":
document.write("wangwang");
break;
case "cat":document.write("miaomiao");
break;
case "fish":
document.write("oh~oh");
break;
}
}
212121:定义一组函数,输入数字,逆转并输出汉字形式
```javascript
num = 456;num[0]=4,num[1]=5,num[2]=6
function reserve() {
var num = window.prompt("input");
var str = "";
for(var i = num.length-1;i>=0;i--){
str += transfer(num[i]);
}
document.write(str);
}
function transfer(targe){
switch(targe){
case "1":
return "壹";
case "2":
return "贰";
case "3":
return "叁";
}
}
222222: 写一个函数,实现n的阶乘
function JC() {
var n = parseInt (window.prompt("输入n"));
var result = 1;
for(var i=1;i<=n;i++){
result*=i;
}
document.write(result);
}
JC();
232323:挑战型作业:
要求输入一个低于十位数的一个数字,输出这串数字的中文大写:
var strNumber = {
'壹','贰','叁','肆','伍','陸','柒','捌','玖','拾'};
var numberOfWeight = {
'','拾','佰','千','万','拾','佰','千','亿'}
var num = parseInt(window.prompt(input));
function chineseNumber(){
不会呀!!!!
}
242424: 递归 求n 的阶乘: 递归只有一个好处 就是代码简洁 但是递归实现代码慢 要一层一层等,复杂的代码一般不使用递归
function JC(n){
if(n==1 ||n==0){
return 1;
}
return n * JC(n-1);
}
JC(5);
252525:作用域:里面的能访问外面的,外面的不能访问里面的
例如:
function test(){
var a = 123;
document.write(b);
function demo(){
var b = 234;
document.write(a);
}
}
test();
这个函数中 demo函数能访问到a,而test函数中不能访问到b
262626: js运行三部曲–> ①语法分析 ②预编译 ③解释执行
预编译:简单两句话 ①函数声明提升:不管执行语句在哪 函数永远提在最前面 ②变量 声明提升
①:imply global 暗示全局变量:即任何变量,如果未经声明就赋值,该值归全局对象(window)所有;即 a = 10 -->window.a = 10;
②:一切声明的变量,全是window的属性;即 var a = 10 —> window.a = 10;
例如:
function test(){
var a = b = 123;
}
test();
console.log(a);
这个过程是先把123赋给b,在声明变量a 再把全局变量b赋给a;此时在外面访问a时输出为undefined,因为a是局部变量在function里面;
272727: 预编译发生在函数执行的前一刻
预编译四部曲:
①创建AO对象(Activation Object)即作用域或者叫执行期上下文
②找形参和变量声明,将变量和形参名作为AO的属性名,值为undefined
③将实参值和形参值统一
④在函数值里面找函数声明,值赋予函数体
例如:
function FN(a){
console.log(a);
var a = 123;
console.log(a);
function a(){
}; /*函数声明*/
console.log(a);
var b = function (){
};
console.log(b);
function d(){
}; /*函数声明*/
}
FN(1);
按照预编译四部曲分析:
AO{
a:1 --> function a(){}
b:undefined
d:function d(){}
}
然后开始执行,一条一条执行:
第一句consol.log(a) 直接从AO里面找到function a(){}并输出;
第二句var a = 123 将AO里面a的值变为123;
第三句从AO中找到a并输出a的值为123;
第四句在预编译中已经读过了 所以执行的时候直接跳过
第五句还是输出123;
第六句将AO里面的b变为function (){};
第七句直接从AO里面找到b并且输出;
function test(a,b){
console.log(a);
c = 0;
var c;
a = 3;
b = 2;
console.log(b);
function b (){
}
function d (){
}
console.log(b);
}
test(1);
AO{
a: 1
b:function b(){
}
c: undefined
d:function d(){
}
}
282828: GO(Global Object) 全局变量 GO === window
例如:
function test(){
var a = b =123;
console.log(window.a); /* undefined */
}
test();
这里面的b未进行定义就赋值 在AO里面找不到 而是储存到了GO里面 而a储存在了AO上面,在GO里面找不到
292929:
console.log(test); /* 从GO里面找*/
function test(test){
/* 从AO里面找 */
console .log(test);
var test = 234;
console.log(test);
function test(){
}
}
test(1);
var test = 123;
GO{
test:function test(){
.....
}
}
AO{
test: function test(){
}
}
303030:
function test(){
console .log(b); /* undefined*/
if(a){
var b = 100;
}
console.log(b); /*undefined*/
c = 234;
console.log(c); /*234*/
}
var a;
test();
AO{
b: undefined;
}
a = 10;
console.log(c); /*234*/
GO{
a: undefined
}
313131:
function bar(){
return foo; /* 相当于 console。log(foo) */
foo = 10;
function foo(){
}
var foo = 11;
}
console.log(bar()); /* 相当于 bar(); */
GO{
bar:function bar(){
.....
}
}
AO{
foo:function foo(){
}
}
323232:
console.log(bar());
function bar(){
foo = 10;
function foo(){
}
var foo = 11;
return foo; /* 相当于 console.log(foo)*/
}
GO{
bar : function bar(){
}
}
AO{
foo: function foo(){
} ---10--11
}
333333:作用域:
每个JavaScript函数都是一个对象,对象中有些属性我们可以访问,但有些我们不可以访问这些属性仅供JavaScript引擎存取,[[scope]]就是其中一个,[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合
作用域链:[[scope]]中所存储的执行期上下文对象的集合,这个集合呈现链式链接,我们把这种链式链接称作作用域链
执行期上下文(AO,GO);当函数执行前一刻,会创建一个称为执行期上下文的内部对象,一个执行期上下文定义一个函数的执行时环境,函数每次执行时对应的执行期上下文都是独一无二的,所以多次调用一个函数会创建多个执行期上下文,当函数执行完闭时会自动销毁它产生的执行期上下文
343434:闭包:
内部函数保存到外部必定生成闭包,闭包会造成原有的作用域链不释放(比如a执行完a的AO应当销毁,但是b定义的时候拿着a的AO返回出去了,所以此时b仍然拿着a的AO),造成内存泄漏
function a(){
var num = 100;
function b(){
num++;
console.log(num);
}
return b;
}
var demo = a();
demo(); 101
demo(); 102
function test(){
var num = 100;
function a(){
num++;
console.log(num);
}
function b(){
num --;
console.log(num);
}
return [a,b]
}
var myArr = test();
myArr[0](); /* 101 */ /* a与b 并级 a能改变test的AO 之后b用的也是改变后的test AO;*/
myArr[1](); /* 100 */
闭包的作用: ①函数累加器 ②可以做缓存(储存结构) ③可以实现封装,属性私有化 ④模块化开发,防止污染全局变量
343434:闭包实现封装,属性私有化
function Deng(name,age){
var prepareWife = "xz";
this.name = name;
this.age = age;
this.devoice = function (){
this.wife = prepareWife;
}
this.changePrepareWife = function(Targe){
this.wife = Targe;
}
this.sayPrepareWife = function(){
console.log(prepareWife);
}
}
var deng = new Deng("xm",32);
353535: 立即执行函数: 此类函数没有声明,在一次执行过后立即释放,不占用空间,适合做初始化工作
针对初始化功能的函数
(function (){
var a = 123;
var b = 234;
console.log(a + b);
}());
让num接收d的返回值 一般都是这样使用立即执行函数
var num = (function test(a,b,c){
var d = a + b + c;
return d
}(100,200,300));
363636:只有表达式才能被执行符号() 执行,
函数定义 分为两种 一种叫函数声明,一种叫函数表达式
例如:
var test = function (){
console.log('a');
}(); /* 这样子能被执行 而且就相当于立即执行函数 执行后test不再代表函数了,这个函数被永久放弃了*/
function test(){
var a = 123;
}(); /* 这叫函数声明,不能被执行符号执行 只能test() 才能执行 因为test相当于表达式 或者可以在function前面加上+ - !就可以让函数执行,因为加上这些符号让函数变成了表达式*/
:373737:因为闭包而产生不想要的结果
function test(){
var arr = [];
for(var i=0;i<10;i++){
arr[i] = function (){
document.write(i + " "); /* 函数体里面的i不会随着for循环的i变化,只有执行时才会知道i的值 可以用立即执行函数实现套现*/
}
}
return arr;
}
var myArr = test();
for(var j=0;j<10;j++){
myArr[j](); /* 打印出十个10 */
}
用立即函数套现实现打印出1到9
:373737:
function test(){
var arr = [];
for(var i=0;i<10;i++){
(function (j){
arr[j] = function (){
document.write(j + " "); /* 立即执行函数读到它立即执行*/
}
}(i))
}
return arr;
}
var myArr = test();
for(var j=0;j<10;j++){
myArr[j](); /* 打印出1--9 */
}
383838:对象:
对象的创建方法:
1.var obj = {
} plainObject 对象字面量/对象直接量
2.构造函数 ①系统自带的构造函数 new object() Array() Number()
②自定义: 因为构造函数和普通函数基本没什么区别,所以人为规定 构造函数的名字必须符合大驼峰式命名规则,即首字母大写 如TheFistName
function Person(){
}
var test = new person();
function Car(){
this.name = 'bmw',
this.height = 1000,
this.weight = 200,
this.lang = 300,
this.health = 100,
this.run = function(){
this.health --;
}
}
var car1 = new Car();
var car2 = new Car();
function Student(name,sex,height){
this.name = name;
this.height = height;
this.sex = sex;
this.weight = 200;
health = 100;
}
var demo = new Student('Lx','male',180);
393939:包装类:
值分为两种,一种是原始值,一种是引用值,原始值的存储方式是存在栈中,它不可以有属性和方法,所以原始值和引用值的两大区别是 存储地址不一样,不可以有属性方法
如果原始值要有属性的话就出现了包装类
例如
var str = ‘abc’
/它会构造出一个字符串对象来 其实执行的是 new String(‘abc’).length 这就是隐式的包装类/
console.log(str.length);
按道理来说原始值是没有属性的,但是它却能输出3
404040: 写一个方法,求一个字符串的长度:
var str = window.prompt('input');
function len(str){
var count = str.length;
for(i=0;i<str.length;i++){
if(str.charCodeAt(i)>255){
count++;
}
}
document.write(count);
}
len(str);
414141:原型,原型链:prototype(原型的终端,可以给prototype赋属性,这样创建它的任何一个对象都能拥有这些属性) constructor(原型都有一个constructor,默认值指向它的构造函数) proto
例如:
Person.prototype.name = 'li';
function Person(){
}
var person = new Person();
424242:创建对象:
var obj = {}
或者
var obj = Object.create(原型)
例如:
var Person = {
name : 'sunny'} /*常用*/
var obj = Object.create(Person); /*一般不这样用*/
document.write(obj) /* document.write 里面输出的其实是 toString的值*/
JavaScript里的精度十个bug 是一种通病
Math.floor(123.999) /*向下取整 输出为123*/
Math.ceil(123.234) /*向上取整 输出为124*/
Math.random() /*取0~1之间的随机数*/
434343:
call 改变this指向 借用别人的函数实现自己的功能
function Person(name,weight){
this.name = name;
this.weight = weight;
}
var person = new Person();
var obj = {
};
Person.call(obj,'LX',100); /*call 的第一个参数会代替掉Person里面的this,所以可以用Person来封装obj,达到直接给obj属性*/
444444:
用call方法实现从别的构造函数中实现自己的功能
function Sit(color,SitSize){
this.color = color;
this.SitSize = SitSize;
}
function Wheel(width,height){
this.width = width;
this.height = height;
}
function Model(len,money){
this.len = len;
this.money = money;
}
function Car(color,SitSize,width,height,len,money){
Sit.call(this,color,SitSize);
Wheel.call(this,width,height);
Model.call(this,len,money);
}
var car = new Car('red',100,500,800,1000,100000);
454545:
apply 与call相似,都是改变this指向,唯一不同的是传参列表不同 他只能传两个数,第一个是指向的函数对象,第二个必须是数组
例如:
function Sit(color,SitSize){
this.color = color;
this.SitSize = SitSize;
}
function Wheel(width,height){
this.width = width;
this.height = height;
}
function Model(len,money){
this.len = len;
this.money = money;
}
function Car(color,SitSize,width,height,len,money){
Sit.apply(this,[color,SitSize]);
Wheel.apply(this,[width,height]);
Model.apply(this,[len,money]);
}
var car = new Car('red',100,500,800,1000,100000);
var Bar = {
a:'002'};
function print(){
Bar.a = 'a';
Object.prototype.b = 'b';
return function inner(){
console.log(Bar.a);
console.log(Bar.b);
}
}
var demo = print();
demo();
474747:继承模式:
function inherit(Target,Origin){
function F(){
F.prototype = Origin.prototype;
Target.prototype = new F(); /*让son继承father的样式,也可以单独增加样式*/
Target.prototype.constructor = Target; /*让son的原型constructor指向它本身*/
Target.prototype.uber = Origin.prototype;
}
}
Father.prototype.lastName = 'LX';
function Father(){
}
function Son(){
}
inherit(Son,Father);
var son = new Son();
var father = new Father();
484848:
污染全局变量的问题:
var name = 'abc';
var init = (function (){
var name = 'ert';
function callName(){
console.log(name);
}
return function (){
callName(); /*留出一个函数作为接口*/
}
}())
init(); /*输出ert,这样形成一个闭包,不会受到全局变量的污染*/
494949:
中括号 的应用
var Deng = {
wife1:{
name:"XiLiu"},
wife2:{
name:"xiDong"},
wife3:{
name:"xiTong"},
wife4:{
name:"xiTing"},
sayWife:function (num){
return this['wife' + num]; /*Deng.wife1 = Deng["wife1"]*/
}
}
505050:
对象的遍历,枚举 for in 数组也能for in
var obj = {
name :'asd',
sex: 'meal',
fon: "gff",
weight:75
}
for(var key in obj){
console.log(key); /*打印出obj的属性名 */
console.log(obj[key]); /*打印出属性值 这里只能用中括号,如果用.key 的话会输出全部为undefined,因为系统会以为key是属性名*/
}
515151:
hasOwnProperty(key) 用来过滤的 看看属性是不是自己的
var obj = {
name :'asd',
sex: 'meal',
fon: "gff",
weight:75,
__proto__:{
lastName:"LX"
}
}
for(var key in obj){
if(obj.hasOwnProperty(key)){
console.log(obj[key]);
}
}
525252:
instanceof 看A原型链上有没有 B的原型
function B(){
}
var A = new B();
console.log(A instanceof B); /*打印 ture*/
535353: this:
1.函数预编译过程 this---> window
2.全局作用域里this----> window
3.call/apply/bind 可以改变函数运行时this指向
4.obj.func();func()里面this指向obj
545454:
arguments.callee:指向函数名的,就相当于函数,当用到立即函数时,没有函数名就可以使用它.例如用递归求一百的阶乘:
var num = (function (n){
if(n == 1){
return 1;
}
return n * arguments.callee(n-1);
}(100))
this指向问题:
var a = 5;
function test(){
a = 0;
alert(a);
alert(this.a);
var a;
alert(a);
}
运行test()和 new test()分别打印出什么
555555: 克隆:分三步:遍历对象 for(var prop in obj) 数组也能for in 因为数组也是特殊的对象 如var arr = [‘a’,‘b’,‘c’] for(var prop in arr){ arr[prop]}
.判断是引用值还是原始值 typeof()看是不是object 如果不是的话就是原始值:
原始值:指的是原始类型的值,也叫基本类型,例如number,string,boolean,null,undefined
存储在栈中的简单数据段,也就是说它们的值直接存储在变量访问的位置
引用值:值得是引用类型的值,如object,function,array,date,RegExp
.判断是数组还是对象 toString(最常用的,无bug) instanceof constructor
toString:将变量转换成字符串的方法,
js中定义了7中数据类型,6中原始的数据类型symbol(es6新定义),除了null和undefined之外其它都有toString方法
1.Boolean:返回ture 或 false
2.number:其toString方法可以传递一个参数radix,这个参数的取值范围是2~36,表示所选的进制
3.string类型:返回指定对象的字符串形式
4.object类型:对于object也就是对象类型 对于null,数组,{}使用typeof判断数据类型都会统一返回object字符串 因为使用typeof无法精确判断,所以使用Object.prototype.toString方法精确判断 其过程就是:获取对象的类名,然后将[object 获取的对象类型的名]组合为字符串,最后返回字符串[object Array]
5.由于js中一切都是对象,任何都不例外,对所有值类型应用Object.prototype.toString.call()
6.判断是否为函数 三、建立相应的数组或对象 四、递归
克隆例题:
var obj = {
name: 'abc',
age:12,
sex:'male'
}
var obj1 = {
};
function deepClone(Origin,Target){
var Target = Target || {
},
toStr = Object.prototype.toString,
Arr = '[Object array]';
for(var prop in Origin){
/*遍历对象*/
if(Origin.hasOwnProperty(prop)){
/*不把原型拿过来*/
if(Origin[prop] !=='null'&& typeof(origin[prop]) == 'object'){
/*判断是引用值还是原始值*/
if(toStr.call(Origin[prop]) == Arr){
/*如果是数组*/
targe[prop] = [];
}else{
targe[prop] = {
};
}
deepClone(Origin[prop],Target[prop]); /*递归*/
}else{
Target[prop] = Origin[prop];
}
}
}
return Target;
}
565656: 三目运算符 : 条件判断 ?是 :否
var num = 12>13 ? 1+1 : 2+2; /*输出4*/
var num = 1 > 0 ? ("10" > "9" ? 1 : 0) : 2; /*先算括号里的 括号里的字符串"10"<"9"输出是0,然后再运算外面的,最后输出为0*/
575757 数组:创建数组的两种方法
var arr = []; 常用的
var arr1 = new Array()
585858:改变原数组
1. push 把数组的最后一位去增加
var arr = [1,2,3];
arr.push(4,5,6) /*数组arr输出为[1,2,3,4,5,6]*/
push的方法如果用函数来写的话:
var arr = [1,2,3]
Array.prototype.push = function(){
for(i = 0;i<arguments.length;i++){
this[this.length] = arguments[i];
}
return this.length;
}
2. pop 把数组的最后一位剪切掉
arr.pop() /*不用传参,传了也没用*/
3.shift :把数组第一位剪切掉
4.unshift 在数组第一位去增加
5.reserve 逆转数组
6.splice(从第几位开始,切去多少的个数,在切口处添加新的东西)
例如:
var arr = [1,3,5,7];
console.log(arr.splice(1,2,7,8,9)); /*打印出切出来的东西*/
console.log(arr); /*打印出arr 为 [1,7,8,9,7]*/
7.sort():给数组排序 升序,如果要排降序的话加个reverse,例如 arr.sort().reverse
例如:
arr = [1,4,6,7,10];
console.log(arr.sort()); /*打印出来为[1,10,4,6,7] 因为都是按字符来排序的*/
如果想要按数字来排序的话:
1.必须写两参数
2.看返回值 1)当返回值为正数时那么后面的数放在前面
2)当返回值为负数时那么前面的数放在前面
3)为0,不动
arr.sort(function(a,b){
if(a>b){
return a - b;
}else{
return a - b;
} /*直接写return a-b 就是升序,写return b-a 就是降序*/
})
如果要给数组排乱序:
arr.sort(function(){
return (0.5 - Math.random());
})
595959:不改变原数组:
1.concat 数组拼接,如:
arr = [1,2,3,4,5];
arr1 = [6,7,8];
console.log(arr.concat(arr1)); /*输出[1,2,3,4,5,6,7,8]*/
2.slice(从该位开始截取,截取的个数) :从数组中截取出来,但是不改变原数组 如:
arr = ['a','b','c','d'];
var arr1 = arr.slice(0,2); /*括号里如果只有1 表示从第b开始截取一直到最后一位 也可以是负数,负数的话表示倒数第几位*/
console.log(arr1,arr); /*打印出a,b a,b,c,d*/
3.join() : /会在每两位位之间增加括号里面的字符串/ 如:
arr = [1,2,3,4];
console.log(arr.join('-')) /*输出为‘1-2-3-4’*/
606060: 类数组 表面上就是对象形式,对象里面的属性要为索引(数字)属性,必须有length属性,最好加上push
类数组的好处是:把数组和对象的特性都拼在了一起
例如:
var obj = {
"0" : 'a',
'1' : 'b',
'2' : 'c',
'3' : 'd',
'length' : 4,
push : Array.prototype.push,
splice : Array.prototype.splice /*让对象形式完全变为数组[]形式展现出来*/
}
push的原理:
Array.prototype.push = function(target){
this[this.length] = target; /*假如参数为'e'时,this指向obj时,即obj[4] = 'e'*/
this.length ++;
}
616161:数组去重,在原型链上操作
var arr = [1,1,1,2,3,4,3,4,5,2]
Array.prototype.unique = function(){
var temp = {
},
arr = [],
len = this.length;
for(var i = 0;i < len;i++){
if(!temp[this[i]]){
/*把每个值取出来不为undefined时。 把数组里的每个值当做属性名,因为属性名不能重复*/
temp[this[i]] = 'abc'; /*属性值‘abc'可以随便取,重复也没事,但是不能去this[i]*/
arr.push(this[i]); /*最后把this[i]放进arr数组里面*/
}
}
return arr;
}
var arr = [1,1,1,1,0,0,'a','a','b','b'] /*输出为['1','0','a','b']*/
626262:判断是什么类型
分两类 原始值 引用值 原始值只要typeof就可以区分了 引用值还要细分
function type(targe){
var temple = {
'[object Array]' : 'array',
'[object Object]' : 'object',
'[object Number]' : 'number - object',
'[object Boolean]' : 'boolean - object',
'[object String]' : 'string - object'
}
if(targe === null){
return null;
}
if(typeof(targe) == 'function'){
return 'function';
}
else if (typeof(targe) == 'object'){
var str = Object.prototype.toString.call(targe);
return temple[str];
}else{
return typeof(targe);
}
}
636363:try{}catch{} try里面的代码错误,不会执行错误后面的代码,并且由catch代替错误的代码执行,如果try里面没错,则catch里面不会执行
try{
console.log('a');
console.log(b); /*b错误了 c也不会执行,并且跳到catch里面执行里面的语句*/
console.log('c');
}catch(f){
/*catch括号里可以随便写什么东西都可以,try的错误信息和错误名是存放在这个f里面的*/
console.log('e')
console.log(f.name + ":" + f.message); /*打印出ReferenceError:'b' is not defined*/
}
console.log('d');
646464:with(){} es5 严格模式中不能用,另外的缺点就是效率低
例如:
var org = {
dp1 : {
name : "lx",
sex : "male",
},
dp2 : {
name : 'xxd',
sex : 'female',
},
}
with(org.dp2) {
/*with括号里填指定的执行期上下文*/
console.log(name); /*打印出为 xxd*/
}
document.write() === with(document){
write('a')}
:656565: Error.name 有六种:
1.EvalError:eval()的使用与定义不一致
2.RangeError:数值越界
3.ReferenceError:非法或不能识别的引用值
4.SyntaxError:发生语法解析错误
5.TypeError:操作数类型错误
6.URIError:URI处理函数使用不当
es 5.0严格模式:即不能支持es3.0 ‘use strict’ 写在第一行 写上这一行代码 就会遵循es 5.0 严格模式
不支持with arguments.callee func caller ,变量赋值前必须声明,局部this必须被赋值Person.call(123),赋值什么就是什么,拒绝重复属性和参数
666666: dom 操作
document.querySelector() 选择出来的元素是静态的,不是实时的
例如用它选择出来三个div,至此之后都是三个div,再怎么修改都跟他没关系
遍历节点数
parentNode --> 父节点
childNodes -->子节点们
firstChild -->第一个子节点
lastChild -->最后一个子节点
nextSibling --> 后一个兄弟节点
previousSibling -->前一个兄弟节点
节点类型:
1.元素节点 ----- 1 (nodeType 的返回值)
2.属性节点 ---- 2
3.文本节点 ------ 3
4.注释节点 ------ 8
5.doucument ----- 9
6.DocumentFragment ----- 11
元素节点树:
parentElement -->返回当前元素的父元素节点(IE9以下不支持)
children --> 只返回当前元素的元素子节点 (就它比较常用)
node.childElementCount === node.children.length 当前元素节点的子元素
firstElementChild -->返回的是第一个元素节点(IE9以下不支持)
lastElementChild -->返回的是最后一个元素节点(IE9以下不兼容)
nextElementSibling /previousElementSibling-->返回后一个/前一个兄弟元素
任何节点都有四个属性:
nodeName:元素的标签名,以大写形式显示,只能读,不能写入
nodeValue:Text节点或comment(注释)节点的文本内容,可读写
nodeType:该节点的类型,只能读
attributes:Element节点的属性集合
检查节点的一个方法:node.hasChildNodes()
document --> HTMLDocument.prototype --> Document.prototype 原型链继承关系
document.documentElement -->指代的就是html
676767: 编辑函数,封装myChildren功能解决以前浏览器的兼容问题
Element.prototype.myChildren = function(){
var child = this.childNodes;
var len = child.length;
var arr = [];
for(i = 0; i< len;i++){
if(child[i].nodeType == 1){
arr.push(child[i]);
}
}
return arr;
}
var div = document.getElementsByTagName('div')[0];
686868: 封装hasChildren()方法,不可用children属性
Element.prototype.hasChildren = function(){
var child = this.childNodes;
var len = child.length;
var arr = [];
for(i = 0; i< len;i++){
if(child[i].nodeType == 1){
arr.push(child[i]);
return true
}
}
return false;
}
var div = document.getElementsByTagName('div')[0];
69669:创建标签:
增:
var div = document.createElement('div'); /*创建元素节点*/
document.body.appendChild(div); /*把创建的div标签放到html的body里面*/
div.innerHTML = 123; /*给div添加内容*/
var text = document.createTextNode('阿信帅帅') /*创建文本节点*/
var comment = document.createComment('this is comment') /*创建注释节点*/
var fragment = document.createDocumentFragment() /*创建文档碎片节点*/
插:
1.appendChild /*相当于剪切操作,并不是复制操作*/
var div = document.getElementsByTagName('div')[0];
var span = document.getElementsByTagName('span')[0];
div.appendChild(span) /*这样span标签就在div标签里面了*/
2.insertBefore /*parentNode.insertBefore(a,b) 一定要在父节点上插入元素节点*/ 例如:
var div = document.getElementsByTagName('div')[0];
var span = document.getElementsByTagName('span')[0]; /*已知span在div里面*/
div.insertBefore(strong,span) /*strong标签插入到div里面并且在span标签前面*/
删:
1.parent.removeChild('标签') /*剪切掉父节点里面的标签 括号里输入想剪切掉的元素节点*/
2.自尽 child.remove() /*想要删掉的元素节点 直接标签.remove()*/
替换:
parentNode.replaceChild(new,origin) /*替换掉父节点里面的某个标签*/
707070:Element节点上的一些元素:
1.innerHTML /*div.innerHTML 给div里赋值,这是覆盖里面的原有值 也可以+=*/
2.innerText/textContent /*可以取里面的文本内容,不会取到标签,也可以赋值,但会覆盖掉原来的所有东西包括里面的标签*/
717171:添加属性和属性值:
div.setAttribute('class','demo') /*括号里前面的是属性名,后面的是属性值*/
div.getAttribute('class') /*他就会打印出属性值demo给你*/
727272: 给div,span,strong分别添加一个属性值class=‘div’,class = ‘span’,class=‘strong’:class 定义一个方法
var all = document.getElementsByTagName('*')
for(i=0;i<all.length;i++){
all[i].setAttribute('this-name','all[i].nodeName')
}
737373:编写一段js脚本生成下面这段dom结构:
<div class = 'example'>
<p class = 'slogan'>阿信,你最帅</p>
</div>
var div = document.createElement('div');
var p = document.createElement('p');
div.setAttribute('class','example');
p.setAttribute('class','slogan');
var text = document.createTextNode('阿信最帅');
p.appendChild(text);
div.appendChild(p);
document.body.appendChild(div);
747474:封装insertAfter 功能类似于insertBefore
Element.prototype.insertAfter = function(targetNode,afterNode){
var beforeNode = afterNode.nextElementSibling; /*选择到目标元素的下一个兄弟元素*/
if(afterNode.nextElementSibling == null){
this.appendChild(targetNode); /*如果目标元素就是最后一个元素的话,直接插入就行了*/
}else{
this.insertBefore(targetNode,beforeNode); /*直接兄弟元素的insertBefore*/
}
}
757575:日期对象:
var date = new Date();
检查循环一亿圈的时间
var firstTime = new Date().getTime();
for(i = 0 ; i<100000000;i++){
}
var lastTime = new Date().getTime();
console.log(lastTime - firstTime);
767676:定时器
var timer = setInterval(function(){
},1000) /*后面的数字为每隔多少毫秒执行一次*/
clearInterval(timer)/*清除定时*/
setTimeout(function(){
},1000) /*1秒钟后执行这个函数*/
clearTimeout() /*清除*/
777777: 写一个三分钟的定时器
<style>
input{
border: 1px solid rgba(0,0,0,.7);
font-size: 14px;
font-weight: 700;
text-align: right;
}
</style>
<body>
minutes:<input type="text" value="0">
seconds:<input type="text" value="0">
<script>
var minutesNode = document.getElementsByTagName('input')[0];
var secondsNode = document.getElementsByTagName('input')[1];
var minutes = 0;
var seconds = 0;
setInterval(function() {
seconds++;
if(seconds == 60){
seconds = 0;
minutes+=1;
}
secondsNode.value = seconds;
minutesNode.value = minutes;
if(minutesNode.value == 3){
clearInterval(1);
}
}, 1000);
</script>
</body>
787878:查看滚动条滚动距离:
window.pageXOffset/pageYOffset /*查看滚动条横 竖 滚动的距离*/
document.documentElement.scrollLeft/Top + document.body.scrollLeft/Top /*兼容性比较混乱,一般都是用两个相加*/
给它封装一个函数:
function getScrollOffset (){
if(window.pageXOffset){
return{
x:window.pageXOffset,
y:window.pageYOffset
}
}else{
return{
x:document.body.scrollLeft + document.documentElement.scrollLeft,
y:document.body.scrollTop + document.documentElement.scrollTop
}
}
}
797979: 查看视口尺寸:
window.innerWidth/innerHeight /*ie8以下不兼容*/浏览器宽度一般都是1440
document.documentElement.clientWidth/clientHeight /*标准模式,任何浏览器都兼容*/
document.body.clientWidth/clientHeight /*怪异模式下的浏览器*/
808080: 查看元素的尺寸:
getBondingClientRect() /*把dom元素选出来然后就可以用了,例如 div.getBondingClientRect() 就会返回一个对象,对象里面有left,right,bottom,top,width,height 返回的结果并不是实时的*/
offsetWidth/Height /*例如 div.offsetWidth可以返回div的宽度 任何dom元素都可以使用 如果是在父集里面 返回的是距离父集的宽高*/
818181: 让滚动条滚动
scroll(x,y),scrollTo(x,y) /*两个方法都是一样的 是让滚动条滚动到某一个位置*/
scrollBy(x,y) /*让滚动条滚动多少像素,可以在之前的数据上进行累加*/
828282:写一个阅读器
<script>
var start = document.getElementsByTagName('div')[0];
var stop = document.getElementsByTagName('div')[1];
var key = true; /*加锁*/
var timer = 0;
start.onclick = function(){
if(key){
timer = setInterval(function(){
window.scrollBy(0,15);
},100)
}
key = false;
}
stop.onclick = function(){
clearInterval(timer);
key = true;
}
</script>
838383:
js间接改变css 可读写:
dom.style.prop 例如: div.style.width = '200px' 获 取的行间的值
window.getComputedStyle(ele,null) /*只能获取 不能写入 获取的值比较准确而且是计算过的 展示的多少就是多少 这个null是获取伪元素的(after,before)*/
ele.currentStyle /*只能读 IE独有的属性*/
848484: 封装一个兼容行方法 getStyle(elem,prop)
function getStyle(){
if(window.getComputedStyle){
return window.getComputedStyle(elem,null)[prop];
}else{
return elem.currentStyle[prop];
}
}
858585:事件
div.on+xxx = function(){
} /*一个事件不能执行多次函数*/
div.addEventListener(type,function,false) 例如: div.addEventListener(click,function(){
},false) /*一个事件可以绑定多个执行函数,但是如果函数是外部引进来的只能绑定一次*/
div.attachEvent('on'+type,function) 例如 div.attachEvent('onclick',function) /*IE独有的,可以为一个事件绑定多个函数 外部调用的函数也行 这里的this指向window*/
868686:
封装一个兼容性事件函数:
function addEvent(elem,type,handle){
if(elem.addEventListener){
elem.addEventListener(type,handle,false)
}else if(elem.attachEvent){
elem.attachEvent('on' + type,function(){
handle.call(elem);
})
}else{
elem['on'+type] = handle;
}
}
878787:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
使用原生js addEventListener,给每一个li元素绑定一个click事件,并输出他们的顺序 例如点击第一个输出0,点击第二个输出1,第三个输出2;
var li = document.getElementsByTagName('li');
for(var i = 0;i<li.length;i++){
(function(i){
li[i].addEventListener('click',function(){
console.log(i);
},false);
}(i))
}
888888:解除事件绑定:
ele.onclick = null;
ele.removeEventListener(click,function(){
},false); /*若绑定匿名函数则无法解除*/
ele.detachEvent('on'+type,function); /*若绑定匿名函数则无法解除*/
898989:事件冒泡:
结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即子元素会冒向父元素(自底向上)
909090:事件捕获
结构上(非视觉上)嵌套关系的元素,会存在事件捕获功能,addEventListener(click,function,true),自父元素捕获至子元素
IE没有捕获事件
先捕获,后冒泡
focus,blur,change,submit,reset,select等事件不冒泡
919191:取消冒泡:
1.W3C标准:event.stopPropagation() /*在每个事件处理函数里面可以写一个形参,系统会帮我们传一个事件对象,这个事件对象就可以阻止冒泡产生*/
div.onclick = function(e){
e.stopPropagation();
}
2.IE独有:event.cancelBubble = true;
929292:阻止默认事件:
1.return false; /*以对象属性的方式注册的事件才生效 如果是addEventListener注册的时间是无效的*/
document.oncontextmenu = function(){
/*取消右键出菜单默认事件*/
return false;
}
2.event.preventDefault() /*W3C标准*/
3.event.returnValue = false /*兼容IE*/
939393:事件对象:
div.onclick = function(e){
console.log(e); /*事件对象会传到这个参数e里面,但是IE不行,IE会在window.event中记录这个对象*/
/*封装一个兼容所有浏览器*/
var event = e || window.event;
console.log(event);
}
939393:事件源对象:
1.event.target /*火狐只有这个*/
2.event.srcElement /*IE只有这个*/
949494:事件委托: 可以把事件绑定到父籍上,这样子元素就都有了事件
利用事件冒泡,事件源对象进行处理:
优点
1.性能:不需要循环所有元素一个一个绑定事件
2.灵活:当有新的子元素时不用重新绑定事件
959595:写一个拖拽方块:
<script>
var div = document.getElementsByTagName('div')[0];
var disX,disY; /*鼠标点击到的那个点的位置*/
div.onmousedown = function(e){
var event = e || window.event;
disX = event.pageX - parseInt(div.style.left);
disY = event.pageY - parseInt(div.style.top);
console.log(123);
document.onmousemove = function(e){
var event = e || window.event;
div.style.left = event.pageX - disX + 'px';
div.style.top = event.pageY - disY + 'px';
}
}
document.onmouseup = function(){
document.onmousemove = null;
}
</script>
969696:鼠标事件 click、 mousedown、 mouseup、 mouseover、 contextmenu、 mouseover = mouseenter、 mouseout = mouseleave
button 来监听鼠标的左右键 0为左键 1为滚轮 2为右键
dom3标准规定 click事件只能监听左键,只能通过mousedown和mouseup来判断鼠标左右键
979797:键盘事件
keydown, keypress, keyup
keydown可以响应任意键盘按键
keypress 只可以响应字符类按键 可以返回ASCII码,转换成相应字符
document.onkeypress = function(e){
console.log(String.fromCharCode(e.charCode)); /*转换成相应字符*/
}
989898:文本操作事件:
oninput,onchange,onfocus,onblur
var input = document.getElementsByTagName('input')[0];
input.oninput = function(e){
console.log(this.value) /*输入框中每次改变都会触发input事件 而change事件聚焦在框中时不会触发change事件,失去焦点时触发事件*/
}
<input type = 'text' value = '请输入用户名' if(this.value == '请输入用户名'){
onfocus = ''} if(this.value == ''){
onblur = '请输入用户名'} ></input>
正则表达式(RegExp)
① var Reg = /abcd/ 这就是一个正则表达式的一种创建方法
var str = 'abcdef';
Reg.test(str); /*如果str里有Reg的字符串,必须是连续的 而且必须也是小写 则返回true 如果reg = /abcd/i 则不区分大小写*/
②str.match(Reg)
③ reg里面也可以放表达式 例如 /[123456789][123456789][123456789][123456789]/ 每一个方括号表示一位,里面的意思是一到九的数字 也可以写成1-9表示1至九的意思
var reg = /[1-9][1-9][123456789][123456789]/g;
var str = "1234fshkg356654sghgldk" ;
console.log(str.match(reg)); /*输出为1234,和3566*/
④ var reg = /[^a][^b][^c]/ ^表示非的意思
999999:JSON
前端的数据如果要传给后端 : JSON.stringify() String ---> JSON
后端的数据传给我们 : JSON.parse() JSON ---> String
js的缺点:js的加载是同步加载的,过多的js文件会影响页面的效率,一旦网速不好,那么整个网站将等待js加载而不进行后续的页面渲染等工作
实现js异步加载:
async w3c标准 只能加载外部脚本 例如:
<script src = "index.js" async></script> 不能把代码写在标签里面
defer:只有ie可以用 也可以将代码写到内部