javascript笔记

2018-08-15  本文已影响0人  珲_cysky2018

是什么

使用场景

区别

组成

变量

作用

储存数据或操作数据

声明与初始化

声明

​ var num (此时没有赋值)

初始化

​ var num = 10 (此时赋值)

方式:

​ var 变量名字

注意:

命名规范

交换变量小案例

思路一:使用第三方变量

思路二:一般适用于数字交换(计算方式)

注释

单行注释:// 一般用在一行代码上

多行注释:/**/ 一般用在函数或者一段代码上

数据类型

原始数据类型

获取变量的数据类型

数字类型

整数和小数

JS中可以表示

八进制:0开头

十进制

十六进制:0x开头

数字类型有范围

最大值 Number.MAX_VALUE

最小值 Number.MIN_VALUE

数值判断

NaN:not a number

isNaN:is not a number

注意

不要用小数去验证小数

不要用NaN验证是不是NaN (使用isNaN())

字符串类型

获取字符串长度:

JS中的转义符:

转义序列 字符
\b 退格
\f 走纸换页
\n 换行
\r 回车
\t 横向跳格 (Ctrl-I)
' 单引号
" 双引号
\ 反斜杠

字符串拼接

使用‘+’号,将多个字符串拼为一个

一个字符串和其他数字拼接,最终结果是字符串

数字类型的字符串和一个数字类型的数字相加得到的是数字类型的数字(发生了隐式转换)

布尔类型

只有两个值,true & false

类型转换

其他类型转数字类型

其他类型转字符串类型

其他类型转布尔类型

Boolean()

console.log(Boolean(1)) // true

console.log(Boolean(0)) //false

操作符

含义:一些符号,用来计算

算数运算符

一元运算符

这个操作符只需要一个操作数就可以运算的符号

二元运算符

类似于算数运算符

需要两个操作数才能运算

三元运算符

表达式1 > 表达式2 ?表达式3 :表达式4

符合运算符

由复合运算符连接起来的表达式

关系运算符

结果是布尔类型

逻辑运算符

结果是布尔类型

赋值运算符

=

字面量

把一个值直接赋值给一个变量

变量的初始化就是以字面量的方式赋值

var num = 10
var flag = true
var str = 'haha'

//以上方式都叫字面量

流程控制

关键字

break

如果在循环中使用,遇到了break,则立刻跳出当前所在循环

continue

在循环中如果遇到了continue关键字,直接开始下一次循环

数组

概念、作用

创建方式

数组元素

数组中存储的每个数据,都可以叫数组的元素,比如:存储了3个数据,数组中3个元素

数组长度

就是数组的元素的个数,比如有3个元素,就说,这个数组的长度是3

数组索引(下标)

数组索引(下标):用来存储或者访问数组中的数据的,索引从0开始,到长度减1结束

数组的索引和数组的长度的关系

数组长度减1就是最大的索引值

设置数组中某个位置的值

arr[3] = 100 //arr数组中索引为3的位置值为100

获取数组中某个位置的值

var result = arr[3];

console.log(result)

数组中储存的类型可以不一样

var arr = [
        function () {
            console.log("eat")
        },
        function () {
            console.log("sleep")
        },
        function () {
            console.log("play")
        },
        function () {
            console.log("drink")
        },
    ];

    arr.forEach(function (ele) {
        ele();
    })

冒泡排序

把所有的数据按照一定的顺序进行排列(从小到大,从大到小)

函数

把一坨重复的代码封装,在需要的时候直接调用即可

作用:代码重复调用

定义:function 函数名字() {
        函数体
}

调用:函数名()

注意:

函数参数

函数的返回值

arguments对象

定义一个函数,如果不确定用户是否传入了参数,或者说不知道用户传入了几个参数,没办法计算

但是,如果在函数中知道了参数的个数,也知道了每个参数的值,就可以计算,怎么办呢?

使用arguments对象,可以获取传入的每个参数的值

arguments对象也可以叫做伪数组

函数的命名方式

函数的定义


   if(true){
     function f1() {
       console.log("哈哈,我又变帅了");
     }
   }else{
     function f1() {
       console.log("小苏好猥琐");
     }
   }
   f1();//在IE8中输出`小苏好猥琐`
var ff;
    if(true){
      ff=function () {
        console.log("哈哈,我又变帅了");
      };
    }else{
      ff=function () {
        console.log("小苏好猥琐");
      };
    }
    ff();

函数作为参数使用

函数可以作为参数使用,如果一个函数作为参数,那么我们说这个参数(函数)叫回调函数

只要是看到了一个函数作为参数使用了,那就是回调函数

函数作为返回值使用

function f1() {
    console.log("this is a function ");
    return function () {
        console.log("this is another function");
    }
}

var ff = f1();  // "this is a function "
ff()    // "this is another function"

函数的作用域

预解析

提前解析代码

this指向

面向对象

编程思想

根据需求,分析对象,找到对象有什么特征行为,通过代码的方式来实现需求,要想实现这个需求,就要创建对象,要想创建对象,就应该显示有构造函数,然后通过构造函数来创建对象.,通过对象调用属性和方法来实现相应的功能及需求

为什么要使用面向对象编程

首先JS不是一门面向对象的语言,JS是一门基于对象的语言,那么为什么学习js还要学习面向对象,因为面向对象的思想适合于人的想法,编程起来会更加的方便,及后期的维护

在JS中如何使用面向对象编程

面向对象的编程语言中有类(class)的概念(也是一种特殊的数据类型),但是JS不是面向对象的语言,所以,JS中没有类(class),但是JS可以模拟面向对象的思想编程,JS中会通过构造函数来模拟类的概念(class)

特征

封装

继承

多态

万物皆对象

创建对象的方式

如何获取该对象(变量)

Json数据格式

一般都是成对,键值对

Json也是一个对象,一般Json合适的数据无论是键还是值都是用双引号引起来

数据类型

内置对象

JS中有三中对象:

基本包装类型

普通变量不能直接调用属性或者方法

对象可以直接调用属性和方法

基本包装类型:本身是基本类型,但是在执行代码的过程中,如果这种类型的变量调用了属性或者是方法,那么这种类型就不再是基本类型了,而是基本包装类型,这个变量也不是普通的变量了,而是基本包装类型对象

原型

作用

构造函数和实例对象之间的关系

        //创建构造函数
function Person(name,age,sex){
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.eat = function () {
            console.log("我饿了,我要吃东西")
        }
    }
        //实例化一个对象
    var hu = new Person('cysky',20,'male');
    console.dir(hu);//实例对象
    console.dir(Person);//构造函数的名字
    
    console.log(hu.constructor===Person);//实例对象的构造器是指向Person的,结果是true,所以,这个实例对象hu就是通过Person来创建的

构造函数创建对象带来的问题--原型使用的原因

调用同样的方法却会创建不同的对象,消耗内存

   function Person(name, age) {
        this.name = name;
        this.age = age;
        this.eat = function myEat() {
            console.log("吃桂花糕");
        };
    }

    var per1 = new Person("小白", 5);
    var per2 = new Person("小黑", 6);

    console.dir(per1);
    console.dir(per2);
    console.log(per1.eat === per2.eat);//false——创建了不同的对象

解决办法:

 function myEat() {
        console.log("我要吃桂花糕")
    }

    function Person(name,age){
        this.name = name;
        this.age = age;
        this.eat = myEat;//将这个方法作为公用方法
    }

    var per1 = new Person('小白', 5);
    var per2 = new Person('小黑', 6);
    console.log(per1.eat === per2.eat);//true——调用的是同一方法

引入原型:

通过原型来解决---------数据共享,节省内存空间

 function Person(name, age){
        this.name = name;
        this.age = age;
    }

    Person.prototype.eat = function () {
        console.log("我饿了,我要吃东西")
    };//通过构造函数的原型添加一个方法

    var per1 = new Person('小黑',20);
    var per2 = new Person('小白',22);

    console.log(per1.eat === per2.eat)//true——调用同一方法

原型的简单语法

function Person(name,age,sex){
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    Person.prototype = {
        //**手动修改构造器指向**
        constructor:Person,
        hieght:180,
        weight:"80kg",
        eat:function(){
            console.log("大家都有饭吃")
        },
        play:function(){
            console.log("一起玩游戏")
        }
    };

    var per1 = new Person('小黑',20,"male");

    console.log(per1.hieght);
    console.log(per1.name);
    per1.play()

原型总结

构造函数、实例对象、原型对象三者之间的关系

利用原型共享数据

function Student(name, age, sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    Student.prototype.eat = function () {
        console.log("今天中午吃外卖")
    };//在Student原型中添加方法
    Student.prototype.weight = "55kg";//在Student原型中添加属性

    var per1 = new Student("小黑", 20, "male");//实例化一个对象
    var per2 = new Student("小白", 22, "female");

    console.log(per1.eat === per2.eat);//true
    console.log(per1.weight);
    console.log(per2.weight);
    console.log(per1.name);
    console.log(per2.name)

相互访问原型中的方法

function Animal(name,age){
        this.name = name;
        this.age = age;
    }

    Animal.prototype.eat = function () {
        console.log("我要吃饭啦");
        this.play()
    };
    Animal.prototype.play = function () {
        console.log("主人陪我玩");
        this.sleep()
    };
    Animal.prototype.sleep = function () {
        console.log("我要睡觉啦")
    };

    var dog = new Animal("小花",3);
    dog.eat()//我要吃饭啦 主人陪我玩 我要睡觉啦

实例对象使用属性和方法层层搜索

 function Person(name, age) {
        this.name = name;
        this.age = age;
        this.eat = function () {
            console.log("我还不饿,不想吃东西")
        }
    }

    Person.prototype.sex = 'male';
    Person.prototype.eat = function () {
        console.log("我饿了,我要吃东西")
    };

    var per1 = new Person("cysky", 22);

    per1.eat();//优先输出实例对象中有的属性和方法
    console.log(per1.sex)//实例对象中没有的属性会在原型里去找

为内置对象添加原型和方法

    //反转字符串
    String.prototype.myReverse = function () {
        for(var i = this.length-1;i>=0;i--){
            console.log(this[i])
        }
    };
    var str = "abcdefg";
    str.myReverse();

将局部变量变成全局变量

(function (形参) {
    var num=10;//局部变量
  })(实参);
    console.log(num);
   (function (window) {
     var num=10;//局部变量
     //js是一门动态类型的语言,对象没有属性,点了就有了
     window.num=num;
   })(window);
   console.log(num);

原型链

使用对象就要先有构造函数

如果有公用的属性和方法,使用原型

实例化对象,并初始化

   function Person(age) {
        this.age = age;
    }//构造函数
    
    Person.prototype.eat = function () {
        console.log("吃东西");
    };//原型
    
    function Student(sex){
        this.sex = sex;
    }
    
    Student.prototype.sayHi = function () {
        console.log("hello");
    };
    
    Student.prototype = new Person(10);

    var stu = new Student("男");
    stu.eat();
    stu.sayHi();//报错:因为改变了原型对象的指向
 function Person(age){
        this.age = age;//构造函数中的this
        console.log(this);
    }
    Person.prototype.eat = function () {
        console.log(this);//原型中的this
        console.log("吃饭了吗");
    };

    var per = new Person(10);
    per.eat();
    console.log(per)//结果同构造函数和原型中的this一样

继承

JS中通过原型来实现继承

function Animal(name, weight) {
        this.name = name;
        this.weight = weight;
    }//动物的构造函数

    Animal.prototype.eat = function () {
        console.log("animal can eat")
    };//动物原型

    function Dog(color){
        this.color = color;
    }//狗的构造函数

    Dog.prototype = new Animal("哮天犬","50kg");//狗的原型指向改变

    Dog.prototype.bitePerson = function () {
        console.log("哼~汪汪~咬死你")
    };//先改变指向,再添加原型

    function ErHa(sex) {
        this.sex = sex;
    }//二哈构造函数

    ErHa.prototype = new Dog('黑白色');//二哈原型

    ErHa.prototype.playHost = function () {
        console.log("哈哈~要坏衣服,要坏桌子,拆家..嘎嘎...好玩,开心不,惊喜不,意外不")
    };

    var erha = new ErHa("雄性");

    console.log(erha.name,erha.weight,erha.color,erha.sex);

    erha.eat();
    erha.bitePerson();
    erha.playHost();

借用构造函数

  function Person(name, age, sex, weight) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.weight = weight;
    }

    Person.prototype.sayHi = function () {
        console.log("您好")
    };

    function Student(name, age, sex, weight, score) {
        Person.call(this, name, age, sex, weight);
        this.score = score;
    }

    var stu1 = new Student("小明", 10, "男", "10kg", "100");
    var stu2 = new Student("小红", 20, "女", "20kg", "120");

    console.log(stu1.name, stu1.age, stu1.sex, stu1.weight, stu1.score);
    console.log(stu2.name, stu2.age, stu2.sex, stu2.weight, stu2.score);

继承组合

原型实现继承
借用构造函数实现继承
组合继承:原型继承+借用构造函数继承

Person.prototype.sayHi = function () {
        console.log("hello")
    };

    function Student(name,age,sex,score){
        Person.call(this,name,age,sex);//使用call方法继承属性
        this.score = score;
    }

    Student.prototype = new Person();//使用原型继承方法

    Student.prototype.eat = function () {
        console.log("eat something")
    };

    var stu = new Student("小黑",20,"男","100分");
    console.log(stu.name, stu.age, stu.sex, stu.score);

    stu.sayHi();
    stu.eat();

拷贝继承

拷贝继承;把一个对象中的属性或者方法直接复制到另一个对象中

function Person() {

    }


    Person.prototype.age = 10;
    Person.prototype.sex = "male";
    Person.prototype.height = "180cm";
    Person.prototype.eat = function () {
        console.log('eat something');
    };

    var obj2 = {};//Person的构造中有原型prototype,prototype就是一个对象,那么里面,age,sex,height,play都是该对象中的属性或者方法

    for (var key in Person.prototype) {
        obj2[key] = Person.prototype[key];
    }

    console.dir(obj2);
    obj2.eat();

call&apply

作用:改变this的指向

 Person.prototype.sayHi = function (x, y) {
        console.log("你好呀:" + this.sex);
        return 1000;
    };

    var per = new Person(10, "男");
    per.sayHi();

    console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

    function Student(name, sex) {
        this.name = name;
        this.sex = sex;
    }

    var stu = new Student("小明","人妖");
    var r1 = per.sayHi.apply(stu, [10,20]);//你好呀:人妖
    var r2 = per.sayHi.call(stu,10,20);//你好呀:人妖
    console.log(r1);//1000
    console.log(r2)//1000

区别:参数传递的方式是不一样的

只要是想使用别的对象的方法,并且希望这个方法是当前对象的,那么就可以使用apply或者是call的方法改变this的指向

apply和call方法实际上并不在函数这个实例对象中,而是在Function的prototype中

    function f1() {
        console.log(this+":======>调用了");
    }
    //f1是函数,也是对象
    console.dir(f1);
    //对象调用方法,说明该对象中有这个方法
    f1.apply();
    f1.call();
    
    console.log(f1.__proto__ === Function.prototype);
    //所有的函数都是Function的实例对象
    console.log(Function.prototype);
    //apply和call方法实际上并不在函数这个实例对象中,而是在Function的prototype中
    console.dir(Function);

bind

闭包

概念

​ 函数A中,有一个函数B,函数B中可以访问函数A中定义的变量或者是数据,此时形成了闭包(不严谨)

闭包模式

​ 函数模式

​ 对象模式

作用

​ 缓存数据,延长作用于链

缺点

​ 缓存数据

总结

​ 如果想要缓存数据,就把这个数据放在外层的函数和里层的函数的中间位置

​ 局部变量是在函数中,函数使用结束后,局部变量就会被自动的释放

​ 闭包后,里面的局部变量的使用作用域链就会被延长

function f2() {
        num = 10;
        return function () {
            num ++;
            return num;
        }
    }

    var ff = f2();
    console.log(ff());
    console.log(ff());
    console.log(ff());
//产生相同的随机数
    function f1() {
        var num = parseInt(Math.random()*10+1);
        return function () {
            console.log(num)
        }
    }

    var ff = f1();
    ff();
    ff();
    ff();

递归

函数中调用函数自己,此时就是递归,递归一定要有结束的条件

//求n个数字的和,5 计算1+2+3+4+5
    var sum = 0;
    for (var i = 0; i <= 5; i++) {
        sum += i;
    }
    console.log(sum);

    function getSum(x){
        if(x===1){
            return 1
        }
        return x + getSum(x-1);
    }

    console.log(getSum(5))

拷贝

浅拷贝

​ 拷贝就是复制,就相当于把一个对象中的所有的内容,复制一份给另一个对象,直接复制,或者说,就是把一个对象的地址给了另一个对象,他们指向相同,两个对象之间有共同的属性或者方法,都可以使用

 var obj1={
      age:10,
      sex:"男",
      car:["奔驰","宝马","特斯拉","奥拓"]
    };
    
    var obj2={};
    
    function extend(a,b) {
      for(var key in a){
        b[key]=a[key];
      }
    }
    extend(obj1,obj2);
    console.dir(obj2);
    console.dir(obj1);
    

深拷贝

​ 拷贝还是复制,深:把一个对象中所有的属性或者方法,一个一个的找到.并且在另一个对象中开辟相应的空间,一个一个的存储到另一个对象中

var obj1={
      age:10,
      sex:"男",
      car:["奔驰","宝马","特斯拉","奥拓"],
      dog:{
        name:"大黄",
        age:5,
        color:"黑白色"
      }
    };

    var obj2={};//空对象
    //通过函数实现,把对象a中的所有的数据深拷贝到对象b中
    function extend(a,b) {
      for(var key in a){
        //先获取a对象中每个属性的值
        var item=a[key];
        //判断这个属性的值是不是数组
        if(item instanceof Array){
          //如果是数组,那么在b对象中添加一个新的属性,并且这个属性值也是数组
          b[key]=[];
          //调用这个方法,把a对象中这个数组的属性值一个一个的复制到b对象的这个数组属性中
          extend(item,b[key]);
        }else if(item instanceof Object){//判断这个值是不是对象类型的
     //如果是对象类型的,那么在b对象中添加一个属性,是一个空对象
          b[key]={};
          //再次调用这个函数,把a对象中的属性对象的值一个一个的复制到b对象的这个属性对象中
          extend(item,b[key]);
        }else{
          //如果值是普通的数据,直接复制到b对象的这个属性中
          b[key]=item;
        }
      }
    }

    extend(obj1,obj2);
    console.dir(obj1);
    console.dir(obj2);
上一篇 下一篇

猜你喜欢

热点阅读