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__: