JavaScript 基础

本文深入探讨JavaScript的引入方式、基本数据类型、语法、流程控制、数据类型操作、函数定义与作用域、常用对象如Date和JSON,以及面向对象编程的概念。详细解析了字符串、数组、对象的特性和操作,Map和Set的使用,Iterator迭代,函数的定义与调用,作用域链,变量提升,以及Date对象和JSON的转换。

一. JavaScript 的两种引入方法

1. 内部引入和外部引入
2.引入的两个位置
<head>
		<meta charset="utf-8" />
		<title></title>
		<!-- 引入的两个位置 -->
		<script type="text/javascript">
			alert("it is my world")
		</script>
</head>
<body>		
		<!-- 引入的两个位置:body 标签的底部 -->
		<script src="js/001.js">	
		</script>
</body>
3. 引入位置不同引起的变化

二. 基本数据类型和基本语法

1.浏览器控制台
console.log() // 在控制台打印内容
2.变量声明

​ var声明一切

3.流程控制
if(){

}else if(){
}

else{
}
4.数据类型
  1. Number类型

    js 不区分小数和整数(不区分int 和float),统一为number类型

    console.log(1/3===(1-2/3)) // return false  避免使用浮点数进行计算
    
  2. 字符串

    不区分单引号和双引号

    PHP中区分单引号和双引号,双引号可以识别变量。

  3. 布尔值

    true 和 false

  4. 比较运算符

    • NaN:not a number 用来说明非数字
      NaN 不等于一切 包括自身
console.log(NaN == 1);  //false
console.log(NaN == NaN);  //false
console.log(NaN == "hello world"); //false



​ isNaN() 用来判断NaN

== 和 ===

​ == 会先进行隐式强制类型转换再进行比较
=== 不允许进行强制类型转换,要求类型和值一致才为true
true == 1 return true; true === 1 return false ;

  1. null 和 unidefined

    null 表示为空,

    unidefined 表示为未定义

  2. 数组

    • 定义:var a = [1,2,3] var b = new Array(1,2,3)

    • 超出下标范围为unidefined

  3. 对象

    定义:中括号定义数组,大括号定义对象,对象内部为键值对的形式

    var people = {
    	name : 'li',
    	age : 90,
    	weight : 100
    }
    

    调用

    console.log(people.name)
    
5.严格检查模式

use strict;

  • 需要放在代码的开头
  • 检查JavaScript随意性带来的一些问题
    • 需要设置编辑器支持es6语法
  • 局部变量尽量使用let定义
6、布尔值为false的情况

null,undefined,空字符串,数字0,空数组,空对象,负值在条件判断中被认为是false

字符串0 不会被认为是false


三.数据类型

1.字符串类型
  • 单引号和双引号包裹的效果相同

  • 字符串的可变性:不可变

    可以使用下标访问,不能使用下标改变

    可以对字符串再赋值

  • 多行字符串

    var str = `
    	hello world
    	hello
    	world
    `
    

    `` 定义多行字符串

  • 模板字符串

    在多行字符的基础上进行定义

    var msg = `${str}`
    console.log(msg)
    
  • 获取字符串长度

    str.length()

  • 常用字符串函数

    str.substr(start[,length])

    根据给定的起始下标和长度截取字符串。

    str.indexOf(subString[, startIndex])

    根据值搜索字符串,返回搜索到字符串的下标

    stringObj.split([separator[, limit]])

    根据分界符将字符串分割为数组

    str.toUpperCase()
    str.toLowerCase()
    
2.数组类型
  1. Array() 可以包含任意的数据类型

arr.length

  • 获取长度

arr.indexOf()

  • 查找成功,根据元素值返回索引
  • 查找失败,返回-1

arr.slice(1,2)

  • 截取数组元素

arr.push() arr.pop()

  • 对栈尾部压入 删除并弹出元素

arr.unshift('a') arr.shift(2)

  • 队列头部压入或者弹出元素

arr.join('-')

  • 数组转换为字符串并设置元素间连接符

    arr
    (4) [1, 2, 3, 4]
    arr.join('-')
    
    "1-2-3-4"
    
  • 数组转字符串 arr.join('')

var arr = ['hello',1,'world','nimade'];
console.log(arr.length);
console.log(arr.indexOf('world')); //2        
console.log(arr[0].slice(1,2)); //e

arr.push('h');
console.log(arr); // [ "hello", 1, "world", "nimade", "h" ]
console.log(arr.pop());  // h
console.log(arr);// [ "hello", 1, "world", "nimade" ]
console.log(arr.unshift('e'));
var string = arr.join('*');
console.log(string); // e*hello*1*world*nimade

数组排序

  • arr.sort()
3.对象类型

对象的属性以键值对的形式呈现,访问一个不存在的属性并不会报错

JavaScript中的对象的键是字符串,值是对象

这里的对象并不是指面向对象

person['weight']; delete person.weight; 这两种访问模式是等价的

  1. 对象的声明

    var person = {
    	name: 'li',
    	age: 50,
    	msg: 'haha'
    }
    
  2. 对象属性的添加

    person.weight = '50'

  3. 对象属性的删减

    delete person.weight

  4. 判断一个属性或方法是否在对象中

    var $bool2 = 'age' in person;

    属性或方法如果是继承则 in 返回结果为 true

  5. 判断一个属性或方法是否只为该对象所拥有(不是继承过来的)

    person.hasOwnProperty('toString')
    false
    
  6. 使用一个不存在的属性:undefined

    即使是在严格检查模式下,访问一个被删除或原本不存在的属性会返回undefined,不会报错。

4.流程控制
if(){
   
}else if(){
         
}else{
    
}
while(){

      }
for(var i = 0; i!=100; i++){
    
}
for(var i in arr){
	console.log(arr[i])
}
// i 遍历的是数组的索引
for(var i of arr){
    console.log(i);
}
// i遍历的是数组的值
5.Map 和 Set

Map和Set都是es6中的新特性,需要编辑器和浏览器支持es6语法

Map:类似python的字典,Set:无序不重复的集合

Map中常用函数:get(),set(),delete(),has(),clear()

// Map 的定义 : Map 类似于python的字典
var map = new Map([['li',100],['han',80],['jun',70]]);

// 获取值
console.log(map.get('li'));
console.log(map.get('hhh'));

// 增加值
console.log(map.set('hahaha',666));

// 删除值
console.log(map.delete('hahaha'));

console.log(map.has('aaa'));
console.log(map.clear());

Set中常用函数:add delete has

// Set:无序不重复的集合
var set = new Set([1,11,1,3]);
set.add(2);
set.delete(1);
console.log(set.has(3));
6.Iterator 迭代

迭代数组

// for in
var arr = [1,2,3,4,5]
for(var x in arr){
	console.log(x);
}

// for of
for(var x of arr){
	console.log(x);
}

迭代map

var map = new Map([['li',100],['han',80],['jun',70]]);
for(var x of map){  // 迭代map的每一个单元,即一个数组
	console.log(x);
}
for(var x of map){
    console.log(x[0]); // 迭代数组中的元素
}

迭代set

var set = new Set([1,11,1,3]);
for(var x of set){
	console.log(x);
}

四.函数

1.定义函数

函数的两种定义

// 正常的定义模式
function abs(a,...rest){
	if(rest.length != 0){
		throw '参数过多';
	}else if(typeof a !== 'number'){
		throw "参数类型错误";
	}
	if(a >= 0){
		return a;
	}else{
		return -a;
	}
}

// 类似java匿名函数的定义模式
var abs2 = function(a){
	// 检错
	if(arguments.length > 1){
		throw '参数过多';
	}else if(typeof arguments[0] !== 'number'){
		throw '参数类型错误';
	}
	if(a>=0){
		return a;
	}else{
		return -a;
	}
}

参数问题与arguments

对于给定个数的函数,可以传入多于形参个数的实参也可以不传入参数,不报错。

js引入arguments 数组用来保存传入的所有参数,而数组的长度就是传入参数的个数

通过 arguments.length 的不同实现不同的函数行为,从而可以实现重载?

es6新特性:可变长参数rest

用来接收除了已经定义之外传入的多余参数,类型为数组,所以也可以获取长度

function rest(a, ...rest){
	for(var x of rest){
		console.log(x);
	}
}
rest(1,2,3)

结果:2 3

类似Java的可变长参数

2.变量的作用域

全局作用域和局部作用域

<script type="text/javascript">
    'use strict';
    // 全局作用域和局部作用域
    var x = 1, y = 1;
    function xx(){
        console.log(y);
        var x = 2;
        console.log(x);
    }
</script>

全局作用域:在所有函数声明和大括号之外定义的变量,贯穿整个js文档,在所有地方都可以使用这个全局变量

局部作用域

  • 函数作用域:函数内声明的变量只能在函数内被访问
  • 块作用域:在一个大括号内用let和const声明的变量,只能在这个大括号内被访问
function rest(a,...rest) {
    for(var x of arguments){
        const a = 1;
        console.log(x);
    }
    console.log(a);
    for(let i = 0;i!=100;i++){

    }
    console.log(i); // i is not defined
    for(var j = 0;j!=100;j++){

    }
    console.log(j); // 没有问题
}

作用域链和变量提升

每一个函数作为一个作用域,如果出现函数嵌套就会出现作用域链。

function a1(){
    b();
    var c = 1;
    function b(){
        var c = 2;
        console.log(c);  // 2
    }
}
a1();

function a2(){
    var c = 1;
    b();
    function b(){
        // var c = 2;
        console.log(c);  // 1
    }
}
a2();

内部函数访问外部函数变量时根据链式查找决定变量是否能被访问。

函数b在内未查找到c的声明便向外查找

function a2(){
    b();
    var c = 1;
    function b(){
        // var c = 2;
        console.log(c);  // undefined
    }
}

函数a2存在提升变量作用域的行为,返回undefined

function xx2(){
    var y = 1 + z; //Uncaught ReferenceError: z is not defined
    console.log(y);
}
function xx3(){
    var y = 1 + z;
    var z = 3;
    console.log(y); // NaN 并不会报错
}

结论:js默认提升变量的作用域,将变量的声明提到最前面,但不进行赋值

内部函数可以调用外部函数定义变量,外部函数不能调用内部函数定义的变量

内部函数和外部函数声明变量同名,内部变量屏蔽外部变量

规范

头部对所有需要使用的变量进行声明

全局对象

函数可被视为变量,所有的全局变量都绑定在windows对象下。

var zz = 1;
			
console.log(zz);
console.log(window.zz)  // 效果相同

// 定义一个old_alert 和 alert 效果相同
var old_alert = alert;
// old_alert(3);

var alert = function(){

}
alert(); // 原本window 下的alert() 函数被重写了

// 他又回来了
var alert = old_alert;
// alert(4);
// 作用域链的问题:局部作用域找不到变量(函数)则向外查找全局作用域,找不到则报错

规范

为了解决在一个全局变量命名冲突的问题:所有的全局变量都默认绑定在window对象下,当引入多个js文件时难免会发生重名问题。

使用一个独立的命名空间以解决这个问题,事实上许多框架也是这么干的。

li.name = 'li';
console.log(li.name);

let 和 var

function let1(){
    while(1){
        var x = 1;
        break;
    }
    console.log(x);  // 1

    while(1){
        let y = 1;
        break;
    }
    console.log(y); // 1

    for(var i = 1;i!=10;++i){
    }
    console.log(i); // 没有报错

    for(let j = 1;j!=10;++j){
    }
    console.log(j); //Uncaught ReferenceError: j is not defined
}
  • 在while中效果相同
  • var的定义变量超出for仍能使用,let定义的变量超出for不能使用

const

const:只读变量,不可修改

规范:常量字母大写表示

// const 关键字
const M = 100; // 只读变量
//m = 200; //Uncaught TypeError: Assignment to constant variable.
3.方法

方法的定义

在对象或类里面定义的函数我们就说它是一个方法。

var person = {
    name : 'li',
    age: function(){
        var now = new Date();
        console.log(this.name, now.getFullYear() - 2000);
    } // 类中的函数我们就说它是一个方法
}
// 方法调用:person.age()

function get_age(){
    var now = new Date();
    console.log(this.name, now.getFullYear() - 2000);			
} // 每一个函数都是一个function对象,this此时指向这个function对象
var person2 = {
    name: 'han',
    age: get_age
} 

this 关键字

每一个函数都是一个function对象,this此时指向这个function对象

apply 关键字

get_age.apply(person2, []);

apply可以改变this指针的指向

  • 第一个参数为this指针指向的对象
  • 第二个参数为对 对象进行的赋值

五.常用对象

1.Date 对象
var now = new Date();
now.getFullYear();
now.getMonth();
now.getDate(); // 获取GMT标准实践
now.getDay();  // 获取星期
now.getHours();
now.getMinutes();
now.getSeconds();
// 以上信息可能被修改,且不同计算机的数据可能不同

now.getTime(); // 获取时间戳,自 1970.1.1 0:00:00 开始至今的毫秒数,全球统一

// to
now.toLocaleString(); // "2020/1/21 上午10:28:47"
2.JSON

what is json?

  • 基于EMCAscript 的轻量级数据交换语言
  • 层次结构
  • 可以提高网络的效率

对象转换JSON,JSON 转换对象

// JSON
var person = {
    name: 'li',
    age: 40
}

// 对象转换为JSON
var a = JSON.stringify(person);

// JSON 转换为对象
var b = JSON.parse(a);

json 和对象的区别

对象的格式化

"{"name":"li","age":40}"  // json
{name: "li", age: 40}     // 对象

六.面向对象编程

1.面向原型继承

对象.__proto__ = 对象

  • 相当于继承的一种写法,但是两者都是对象
  • 已有属性和方法会覆盖和重写原型中的属性和方法,但是没有的会被继承
var person = {
    name: 'li',
    age: 17,
    run: function(){
        console.log(this.name + '  run..');
    }
}

var tom = {
    name: 'tom',
    age: 18,
    run: function(){
        console.log('t' + '  run..');
    } 
}
tom.__proto__ = person; 
2.class继承

class定义一个类:构造器 + 方法

class 关键字构建的类中属性的定义都在构造器中完成

class animal{
    constructor(name) {  // 类中的构造器,所有属性在构造器内定义
        this.name = name;
    }
    hello(){
        alert('I am ' + this.name);
    }
} // 类
var lion = new animal('lion'); // 定义一个对象

class 继承

 class cat extends animal{
     constructor(name,age) {
         super(name);
         this.age = age;
     }
     get_age(){
         alert(this.age);
     }
 }
 // 定义对象
 var cat1 = new cat('tom', 18);

原型链

原型链是一个环形链,最后归于object

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值