淘先锋技术网

首页 1 2 3 4 5 6 7

JavaScript核心语法-EcmaScript

一. 表达式

  • 表达式由运算符、操作数组成,会有一个表达式结果。
  • 表达式可以放置在任何位置,可以是函数调用表达式等。
  • 操作数的个数决定运算符的元数。

1. 变量未声明,进行变量的操作:输出、运算,会发生ReferenceError错误。

console.log(34 + val);//Uncaught ReferenceError: val is not defined
// 特殊情况
console.log(typeof val);//undefined,不推荐此操作

2. 数值与字符串比较、数值与布尔值比较、字符串与布尔值比较

  • 比较大小的本质:数值比较
    • 数值型数据比较,重点在于两个浮点数相等比较。(两个浮点数的差小于等于浮点数误差值)
    • 字符串比较的是字符的UNICODE编码值。
  • 字符串与数值比较:字符串转换为数值型数据,再进行比较。若是字符串不能转换为数值,则为NaN,比较结果始终为false。(NaN不能与任何值比较,包括其本身)。
  • 字符串与布尔值比较:字符串转换为数值型数据,布尔值转换为数值型数据,再进行比较。若是字符串不能转换为数值,则为NaN,比较结果始终为false。
  • 数值与布尔值比较:布尔值转换为数值型数据,再进行比较。
  • 字符串与字符串比较:逐个比较字符串中字符的UNICODE编码值。

二. 语句

  • 对于多分支条件结构,特别注意其隐含的条件。
  • 对于switch语句,比较的是全等,只能作相等判断,不能做范围判断。

三. 代码调试(debug)技巧

  • 代码调试的目的:
    • 定位错误的原因和位置,并解决错误。
  • 错误:
    • 语法错误(一般会报错);
    • 逻辑错误(一般不报错);
  • 以前调试JS方式:
    • alert();//不推荐
    • console.log();
  • 断点调试:
    • Chrome Google调试JS代码,F12(开发者工具)–>Sources(选择要调试的文件)–> 打断点。
    • 代码执行到断点处停止。
    • 注意Watch中变量值的变化。

四. 冒泡排序

// 方式一:
原数组: 23, 45, 34, 0, 23, 12, 0, 67, 34, 0, 17  一共11个数
第一次结果: 23, 34, 0, 23, 12, 0, 45, 34, 0, 17, 67  确定1个数,内部比较次数10次
第二次结果: 23, 0, 23, 12, 0, 34, 34, 0, 17, 34, 67  确定2个数,内部比较次数9次
第三次结果: 0, 23, 12, 0, 23, 34, 0, 17, 34, 34, 67  确定3个数,内部比较次数8次
第四次结果: 0, 12, 0 ,23, 23, 0, 17, 34, 34, 34, 67  确定4个数,内部比较次数7次
第五次结果: 0, 0, 12, 23, 0, 17, 23, 34, 34, 34, 67  确定5个数,内部比较次数6次
第六次结果: 0, 0, 12, 0, 17, 23, 23, 34, 34, 34, 67  确定6个数,内部比较次数5次
第七次结果: 0, 0, 0, 12, 17, 23, 23, 34, 34, 34, 67  确定7个数,内部比较次数4次
第八次结果: 0, 0, 0, 12, 17, 23, 23, 34, 34, 34, 67  内部比较次数3,验证数据是否排序完:数据无任何交换

结论: 数据最多进行: 数组.length - 1轮排序。
// 方式二:
原数组: 23, 45, 34, 0, 23, 12, 0, 67, 34, 0, 17  一共11个数
i = 0; j = i + 1;

冒泡排序优化

  • 如何判断数据排序完成?
    • 数据不再交换。
// 方式一:推荐,效率高
var nums = [23, 45, 34, 0, 23, 12, 0, 67, 34, 0, 17];//原数据
function sort(arr){
    var temp;//数据交换中间值
    var isSort;
    var count = 0;

    console.time('start');//计时开始
    for(var i = 0, len = arr.length - 1; i < len; i++){
        count++;
        isSort = true;//检测每轮排序是否完成
        for(var j = 0; j < len-i; j++){
            count++;
            if(arr[j] > arr[j+1]){
                temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
                isSort = false;
        }
    }
        if(isSort){
            break;
        }
    }
    console.timeEnd('start');//计时结束,并输出
    console.log(count);
    return arr;
}

// 方式二
var nums = [23, 45, 34, 0, 23, 12, 0, 67, 34, 0, 17];//原数据
function sort(arr) {
    console.time('start'); //计时开始
    var temp; //交换数据的第三者
    var flag; //排序完成标识
    var count = 0
    for (var i = 0, len = arr.length; i < len; i++) {
        flag = true;
        count++;
        for (var j = i + 1; j < len; j++) {
            count++;
            if (arr[i] > arr[j]) {
                temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
                flag = false;
            }
        }
        if (flag) {
            break;
        }
    }
    console.timeEnd('start'); //计时结束,并输出
    console.log(count);
    return arr;
}

五. 逻辑题

1. 输入某年某月某日,判断这一天是这一年的第几天?

实现方式一:switch

// 判断是否闰年,闰年2月29天,平年2月28天
function isLeapYear(year){
    return (year % 4 === 0 && year % 100 !== 0)||(year % 400 === 0);
}
function getDays(year,month,day){
    var days = day;
    for(var i = 1; i < month; i++){
        switch (i) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                days += 31;
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                days += 30;
                break;
            case 2:
                if (isLeapYear(year)) {
                    days += 29;
                } else {
                    days += 28;
                }
                break;
        }
    }
    return days;
}

实现方式二:数组

// 判断是否闰年,闰年2月29天,平年2月28天
function isLeapYear(year){
    return (year % 4 === 0 && year % 100 !== 0)||(year % 400 === 0);
}
function getDays(year, month, day) {
    var days = day; //当前月天数
    var arrDays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; //闰年每月
    for (var i = 0, len = month - 1; i < len; i++) {
        if (i == 1) {//2月天数处理
            arrDays[i] = isLeapYear(year) ? 29 : 28;
        }
        days += arrDays[i];
    }
    return days;
}

六. JavaScript代码执行过程

  • JavaScript代码的执行是由浏览器中的JavaScript解析器(引擎)来执行的。
  • JavaScript解析器执行JavaScript代码分为两个过程:
    • 预解析过程;
    • 代码执行过程;

预解析过程:

  1. 把变量的声明提升到当前作用域的最前面,只提升变量声明,不提升变量赋值。
  2. 把函数的声明提升到当前作用域的最前面,只提升函数声明,不提升函数表达式和函数调用。
  3. 先提升变量声明,再提升函数声明。

七. 对象成员遍历和删除

  • for…in,可以遍历对象或其原型中的可枚举成员。
  • delete,可以删除对象或原型中的可配置成员。
  • in, 检测对象或其原型中是否存在某个属性。

八. 基本数据类型和引用数据类型

  • 基本数据类型:number、string、boolean、null、undefined;
  • 引用数据类型:Object;
  • JavaScript中没有堆栈概念,使用堆栈概念,便于理解JavaScript程序。
  • 栈内存:由操作系统分配和释放,存储基本数据类型数据,引用数据类型地址。
  • 堆内存:由程序员开辟堆内存空间,程序员未手工释放,则由垃圾回收器回收并释放。存储引用数据类型数据。

1. 基本数据类型

  • 基本数据类型,变量存储值本身,存储在栈内存中。
  • 基本数据类型复制的是值本身。
var n1 = 10;
var n2 = n1;//复制n1值
n1 = 20;

简单数据类型存储-示意图:
在这里插入图片描述

var x = 10;
var y = 20;
add(x, y);
function add(a, b){
    a = a + 10;
    b = b + 20;
}

简单数据类型作为函数参数:
在这里插入图片描述

2. 引用数据类型

  • 引用数据类型,变量存储引用数据类型的地址,存储在栈内存中。
  • 堆内存中存储引用数据类型的数据。
  • 复制的是引用数据类型的地址。
  • 栈内存与堆内存是一对一或多对一的关系。
function Person(name, age){
    this.name = name;
    this.age = age;
    this.sayHi = function(){};
}
var per = new Person('ls', 20);
var son = per;

引用数据类型存储-示意图:
在这里插入图片描述

function Person(name, age){
    this.name = name;
    this.age = age;
    this.sayHi = function(){};
}
var per = new Person('ls', 20);
function test(obj){
    obj.name = 'zs';
}
test(per);

引用数据类型作为函数参数:
在这里插入图片描述

九. 内置对象

1. Math对象

随机生成[min,max]间的整数:

function getIntRandom(min, max){
    return Math.ceil(Math.random()*(max-min)+min);
}
// 附加:生成[0,255]之间的RGB颜色值
function randomRGB(min, max){
    var colorValues = new Array(3);
    for(var i = 0, len = colorValues.length; i < len; i++){
        colorValues[i] = getIntRandom(min,max);
    }
    return 'rgb('+colorValues[0]+','+colorValues[1]+','+colorValues[2]+')';
}

2. Date对象

  • 两个日期时间对象可以相减,实际上是各自日期时间对象调用了valueOf()方法,转换为时间戳相减。

3. Array对象

sort方法

  • sort方法,默认情况下(无参数)是按照ASCII码值进行排序。先将数组中的元素转换为字符串(toString()),然后按照ASCII码值排序。
  • 排序规则:compareFunction,返回大于0,等于0,小于0。
// 若排序的是数值型数据,排序规则(按照从小到大排序:a-b,按照从大到小排序:b-a)
function compareFunction(a, b){
    return a - b;
}
// 若排序的是字符串型数据,排序规则(按照ASCII进行排序,大写字母:65~90,小写字母:97~122)
function compareFunction(a, b){
    // 不区分大小写排序
    var a = a.toUpperCase();
    var b = b.toUpperCase();
    if(a < b){
        return -1;
    }
    if(a > b){
        return 1;
    }
    return 0;
}
// 模拟sort方法内部实现
function sort(arr, compareFunction) {
    var temp; //中间值,负责交换数据
    var flag; //检测是否排序完成
    for (var i = 0, len = arr.length - 1; i < len; i++) {
        flag = true;
        for (var j = 0; j < len - i; j++) {
            if (compareFunction(arr[j], arr[j + 1]) > 0) { //arr[j] > arr[j+1],控制排序规则
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                flag = false;
            }
        }
        if (flag) {
            break;
        }
    }
    return arr;
}
// 模拟join方法
function join(arr, separator) {
    //参数处理
    var arr = arr || [];
    var separator = separator?',':separator;
    var len = arr.length;
    if (len === 0) {
        return '';
    }
    var str = arr[0];
    for (var i = 1; i < len; i++) {
        str += separator + arr[i];
    }
    return str;
}
// 模拟reverse方法
function reverse(arr) {
    if (!(arr instanceof Array)) {
        throw new TypeError('not a define or not a array');
    }
    var temp; //中间值,用于交换数据
    var lastIndex = arr.length - 1; //最后一个元素的索引值
    for (var i = 0, len = parseInt(arr.length / 2); i < len; i++) {
        temp = arr[i];
        arr[i] = arr[lastIndex];
        arr[lastIndex--] = temp;
    }
    return arr;
}
// 数组去重:保留前者,删除后者
function clearRepeat(arr) {
    for (var i = 0, len = arr.length-1; i < len; i++) {
        for (var j = i + 1; j < len; j++, len = arr.length) { //实时更新len,数组长度
            if (arr[i] === arr[j]) {
                arr.splice(j, 1);
                j--;
            }
        }
    }
    return arr;
}

4. 字符串

  • 字符串不可变。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yfzXswNW-1583755385034)(images/string.png)]

  • 当大量拼接字符串的时候,会有性能问题。(不推荐字符串的大量拼接)
  • 字符串的所有方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串。

十. 函数

  • 函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。
  • 函数是一个特殊的对象,但对象都是通过函数创建的。
  • 函数的数据类型始终是:function。
  • 函数创建的方式:
// 函数创建:
var func = new Function('代码');
func();//函数调用
console.log(typeof func);//function,函数的类型永远是function
console.log();
// 创建有参函数:
var func = new Function('a, b, c', 'console.log(a+b+c);');
func(1,2,3);//调用函数

// 函数声明-在JavaScript预解析过程会提升
function methodName(){
    // 函数体内代码
}
// 函数表达式声明
var methodName = function (){
    // 函数体内代码
}