JavaScript学习笔记(二)

4、函数

4.1、定义函数

定义方式一

绝对值函数

    function abs(x) {
        if(x>=0){
            return x;
        }else{
            return -x;
        }
    }

function指出这是一个函数定义;

  • abs是函数的名称;
  • (x)括号内列出函数的参数,多个参数以,分隔;
  • { ... }之间的代码是函数体,可以包含若干语句,甚至可以没有任何语句。

一旦执行到 return 代表函数结束,返回结果!
如果没有执行 return ,函数执行完也会返回结果,结果就是 undefined

定义方式二

var abs = function(x){
        if(x>=0){
            return x;
        }else{
            return -x;
        }
}

function(x){…}这是一个匿名函数。但是可以把结果赋值给abs,通过abs就可以调用函数!
方式一和方式二等价!

调用函数

abs(10)    //10
abs(-10)   //10

参数问题:JavaScript可以传任意个参数,也可以不传递参数~
参数进来是否存在的问题?
假设不存在参数,如何规避?

function abs(x) {
        //手动抛出异常来判断
        if (typeof x !== 'number') {
            throw 'Not a Number';
        }
        if (x >= 0) {
            return x;
        } else {
            return -x;
        }
    }

arguments

特性:

  • arguments对象和Function是分不开的。

  • 因为arguments这个对象不能显式创建。

  • arguments对象只有函数开始时才可用。

arguments是一个js免费赠送的关键字;
代表,传递进来的所有的参数,是一个数组!

function abs(x) {
        console.log("x=>" + x);
        
        for (var i = 0; i < arguments.length; i++) {
            console.log(arguments[i]);
        }
        
        if (x >= 0) {
            return x;
        } else {
            return -x;
        }
    }

结果:

>abs(10)
x=>10
10
<-10

Javascript并没有重载函数的功能,但是Arguments对象能够模拟重载。Javascrip中每个函数都会有一个Arguments对象实例arguments,它引用着函数的实参,可以用数组下标的方式"[]"引用arguments的元素。arguments.length为函数实参个数,arguments.callee引用函数自身。

问题:arguments 包含所有的参数,我们有时想使用多余的参数来进行附加操作。需要排除已有参数~

rest

以前:

if(arguments.length>2)
 {
     for(var i = 2 ;i<arguments.length;i++){
         //....
     }
 }

ES6 引入的新特性,获取除了已经定义的参数之外的所有参数~

function aaa(a,b,...rest) {
        console.log("a->"+a);
        console.log("b->"+b);
        console.log(rest);
    }

rest 参数只能写在最后面,必须用…标识。
注意return语句:JavaScript引擎有一个在行末自动添加分号的机制

function f() {
    return { name: 'f' };
}

f(); // { name: 'f' }

如果把return语句拆成两行:

function f() {
    return
        { name: 'f' };
}

f(); // undefined

由于JavaScript引擎在行末自动添加分号的机制,上面的代码实际上变成了:

function f() {
    return; // 自动添加了分号,相当于return undefined;
        { name: 'f' }; // 这行语句已经没法执行到了
}

所以正确的多行写法是:

function f() {
    return { // 这里不会自动加分号,因为{表示语句尚未结束
        name: 'f'
    };
}

4.2、变量的作用域

在javascript中,var 定义变量实际使用作用域的。
假设在函数体中声明,则在函数体外不可以使用~(非要想实现的话,后面可以研究一下闭包

function yyc() {
        var x = 1;
        x = x + 1;
    }

    x = x + 1;//Uncaught ReferenceError: x is not defined

如果两个函数使用了相同的变量名,只要在函数的内部,就不冲突

function yyc() {
        var x = 1;
        x = x + 1;
    }

function yyc2() {
        var x = 'AS';
        x = x + 1;
    }

内部函数可以访问外部函数的成员,反之则不能

function yyc() {
        var x = 1;
        
        //内部函数可以访问外部函数的成员,反之则不能
        function yyc2() {
            var y = x + 1;//2
        }

        var z = y + 1;//Uncaught ReferenceError: y is not defined
    }

假设,内部函数变量和外部函数变量,重名!

function yyc() {
        var x = 1;

        //内部函数可以访问外部函数的成员,反之则不能
        function yyc2() {
             var x = 'A';
             console.log('inner'+x);//innerA
        }
        console.log('outer'+x);//outer1
        yyc2();
    }

假设在javascript中函数查找变量从自身函数开始~,由“内”向“外”查找,假设外部存在这个同名的函数变量,则内部函数会屏蔽外部函数变量。

提升变量的作用域

function y () {
        var x ="x"+y;
        console.log(x);
        var y = 'y';
    }

结果:xundefined
说明:js执行引擎,自动提升了y的声明,但不会提升变量y的赋值;如下所示:

function y2 () {
        var y;
        var x ="x"+y;
        console.log(x);
        var y = 'y';
    }

这个是在JavaScript建立之初就存在的特性。养成规范:所有的变量定义都放在函数的头部,不要乱放,便于代码维护;

function y2() {

        var y = 1,
            x = y + 1,
            z, i, a;//undefined
        //之后随意用
    }

全局函数

var x = 1;
function f() {

    console.log(x);
}
f();
console.log(x);

全局对象 window

var x = 'sss';
alert(x);
alert(window.x);//默认所有的全局变量,都会自动绑定在window对象下;

alert()这个函数本身也是一个window变量,即:window.alert() 等价于 alert()

var x = 'sss';
window.alert(x);
 var old_alert = window.alert;//old_alert(x);

 window.alert = function(){

 };
 //发现alert()失效了
 window.alert(123);//123出不来

 //恢复
 window.alert  = old_alert;
 window.alert(456);//456可以出来

JavaScript实际上只有一个全局作用域,任何变量(函数也可以视为变量),假设没有在函数作用范围内找到,就会向外查找如果在全局作用域都没有找到,报错RefrencceError

规范

由于所有的全局变量都会绑定到我们的window 上。如果不同的js文件,使用相同的全局变量,冲突—>如何能够减少冲突?

//唯一全局变量
    var y = {};

    // 定义全局变量
    y.name = 'yyc';
    y.add = function (a, b) {
        return a + b;
    }

把自己的代码全部放入自己定义的唯一空间名字中,降低全局命名冲突的问题~
jQuery

局部作用域 let

function aaa() {
        for(var i = 0; i<100;i++){
            console.log(i);
        }
        console.log(i+1);//问题: i出来这个作用域还可以使用?

    }

因此 ES6引入 let 关键字,解决局部作用域冲突问题!

function aaa() {
        for(let i = 0; i<100;i++){
            console.log(i);
        }
        console.log(i+1);//Uncaught ReferenceError: i is not defined
    }

建议都用 let 去定义局部作用域的变量;

常量 const

在 ES6 之前,常量都是用大写字母命名的;建议不要修改这样的值;

var PI = 3.14;
console.log(PI);

PI  = 123;//这个值是可以改变的
console.log(PI);

在 ES6 引入了常量这个关键字const

const PI =  3.14;//只读变量
console.log(PI);
PI  = 123;//Uncaught TypeError: Assignment to constant variable.

4.3、 方法

定义方法

方法就是把函数放在对象 的里面, 对象 只有两个东西:属性和方法

var yyc = {
        name: '大王',
        birth:2000,
        //方法
        age: function () {
          // 今年  -  出生的年
            var now = new Date().getFullYear();//getFullYear() 方法可返回一个表示当下年份的 4 位数字。
            return now-this.birth;
        }
    }
    // 属性
    yyc.name;
    //方法,一定要带()
    yyc.age();

this.代表什么?可以拆开成下面这样:

function getAge() {
        var now = new Date().getFullYear();
        return now - this.birth;
    }

    var yyc = {
        name:'大王',
        birth:2000,
        age:getAge
    }
    //这样是可以调用到的
    //yyc.age()
    //20

    //这样是调用不到的
    //getAge()   window调用
    //NaN   not a number 

注意:请使用 isNaN() 来判断一个值是否是数字。原因是 NaN 与所有值都不相等,包括它自己。

this是无法指向的,是默认指向调用它的那个对象;

apply()

在js中可以控制 this 指向

function getAge() {
        var now = new Date().getFullYear();
        return now - this.birth;
    };

    var yyc = {
        name:'大王',
        birth:2000,
        age:getAge
    }

    var cyy = {
        name:'老大',
        birth:1999,
        age:getAge
    }
    //通过apply将
    getAge.apply(yyc,[]);//this指向了yyc,参数为空
    getAge.apply(cyy,[]);

5.内部对象

标准对象

typeof 123
"number"
typeof 1.1
"number"
typeof '132'
"string"
typeof true
"boolean"
typeof NaN
"number"
typeof []
"object"
typeof {}
"object"
typeof Math.abs
"function"
typeof undefined
"undefined"

5.1 Date

基本使用

var now = new Date();//Sun Mar 22 2020 19:24:11 GMT+0800 (中国标准时间)
    now.getFullYear();//年
    now.getMonth();//月
    now.getDate();//日
    now.getDay();// 星期几
    now.getHours(); //时
    now.getMinutes();// 分
    now.getSeconds();//秒

    now.getTime();//时间戳   全世界统一  1970  1.1 0:00:00 到现在的毫秒数
    console.log(new Date(1584876606480));时间戳转化为时间

转换

now = new Date(1584876606480)
Sun Mar 22 2020 19:30:06 GMT+0800 (中国标准时间)
now.toLocaleString()//注意:调用时一个方法   本地时间
"2020/3/22 下午7:30:06"
now.toGMTString()
"Sun, 22 Mar 2020 11:30:06 GMT"

5.2、JSON

json是什么?

早期,所有数据传输习惯使用 XML 文件!

  • JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。
  • 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
  • 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

在 javascript 中一切都是对象,任何 js 支持的类型都可以用 JSON 来表示;number、string …
格式:

  • 对象都用 { }
  • 数组都用 [ ]
  • 所有的键值对都是用 key:value

JSON字符串和JS对象的转化:

var user = {
        name:'yyc',
        age:3,
        sex:'男'
    }

    //对象转化为json字符串
    var jsonUser = JSON.stringify(user);

    //json 字符串转化为对象  参数为json字符串
    var obj = JSON.parse('{"name":"yyc","age":3,"sex":"男"}');//如果里面是双引号外面就用单引号

很多人搞不清楚,JSON和js对象的区别

var obj = {a:'hello',b:'h'};
vvar json = '{"a":"hello","b":"ssm"}';

6、面向对象编程

原型对象

javascript、java、c#…面向对象;javascript有些区别!
类:模板 原型对象
对象:具体的实例
在javascript这个需要换一下思维方式!
原型:

var Sutdent = {
        name: 'sss',
        age: 3,
        run: function () {
            console.log(this.name + "run ...")
        }
    };

    var lihua = {
        name: "lihua"

    };
    //原型对象
    yyc.__proto__ = Sutdent;

    var Bird = {
        fly: function () {
            console.log(this.name + "flying...")
        }
    };
    lihua.__proto__ = Bird;
function Student(name) {
        this.name = name;
    }

     // 在ES6 之前给Student新增一个方法
    Student.prototype.hello = function () {
        alert("hello");
    };

class 继承

class 关键字,实在ES6引入的
1.定义一个类,属性,方法

//定义一个学生类
class Student{
       // constructor 构造器
        constructor(name) {
            this.name = name;
        }

        hello(){
            alert("hello");
        }
    }
    var lihua = new Student("lihua");
    var xiaohong = new Student("xiaohong");
    lihua.hello();
    

2.继承

<script>
    //定义一个学生类
    class Student{
        constructor(name) {
            this.name = name;
        }

        hello(){
            alert("hello");
        }
    }
        class XiaoStudent extends Student{
            constructor(name , grade) {
                super(name);
                this.grade = grade;
            }

            myGrade(){
                alert('我是小学生');
            }
        }
    
    var lihua = new Student("lihua");
    var xiaohong = new XiaoStudent("xiaohong",1);
</script>

本质:查看对象原型
在这里插入图片描述

原型链

__proto__:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值