javascript基础

javascript toturior

一小时入门JavaScript:https://www.youtube.com/watch?v=W6NZfCO5SIk&ab_channel=ProgrammingwithMosh

JS基础语法练习题:https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/

1. JS introduction

1.1 JS intruduction

  • 什么是javascript

  • javascript可以做什么

  • javascript代码运行在什么地方

  • javascript vs ECMAScript

javascript是一种流行的编程语言,可以写前端和后端代码。

曾经在很长一段时间内,JS只能在浏览器中用来创建交互式的web页面。现在则可以用来实现web/mobile应用,实时网络apps,命令行工具,游戏等。

原生的javascript代码只能运行在浏览器中,所有浏览器都有javascrript引擎。有了node之后,JS代码可以运行在node中。所以,JS代码可以运行在浏览器或者node中,浏览器和node为JS提供了运行时环境。

ECMAScript是一个specification,JS是一个编程语言。

1.2 Setup 开发环境

编辑器:vscode

node

插件:live server

1.3 JS基础

js脚本在html文件中可以放到head或body中,最佳实践是放到body的尾部。

原因1:浏览器从上到下解析HTML文件并渲染元素,如果放在head或者body的上面会导致浏览器在运行JS脚本的时候页面空白,需要在页面元素都出现之后再运行JS脚本;

原因2:JS脚本可能会使用元素,这样可以确保脚本使用的元素都已经被浏览器渲染完成。

1.4 Separation of concerns

实际上一个项目会有很多JS脚本,JS脚本不可能全部放在HTML文件中。我们创建单独的index.js文件,然后在HTML中引用js文件。

<script src="index.js"></script>

1.5 JS in node

上面都是在浏览器中运行JS脚本,现在我们在node中运行JS脚本。

node index.js

Node: a program includes google’s V8 javascript engine. a runtime environment for executing JS scripts.

2. JS basic

2.1 Variables & constant

variable

在ES6之前使用var声明变量,在ES6之后使用let声明变量。

var可以对一个变量声明多次,let只能对一个变量声明一次。

var name = "James";
var name = "David";
console.log(name);

var可以对一个变量声明多次,但这会导致一些问题。。

let camper = "James";
let camper = "David";

let只能对一个变量声明一次,上面的代码会报错:Uncaught SyntaxError: Identifier 'name' has already been declared

变量的命名规则:

  1. 变量有大小写字母、数字、下划线、$组成
  2. 不能使用保留关键词
  3. meaning & descriptive
  4. 不能以数字开头,不能包含空格或中划线
  5. 建议驼峰命名法,大小写敏感

声明多个变量:

let firstName = 'yin', lastName = 'bai'; // not recommend
let firstName = 'yin'; // recommend
let lastName = 'bai';  // recommend
constants

ES6还提出了一个定义常量的关键字const,const除了拥有let的所有特性之外,声明的变量不能被修改,即常量。

const声明的变量名应该全大写。

You should always name variables you don’t want to reassign using the const keyword.

const interestRate = 0.3;

2.2 数据类型

Primitive types

JS中有两种数据类型,一种是primitive/value type,一种是reference type。primitive类型包括以下几种:

  • String
  • Number
  • Boolean: true or false
  • undefined:只声明变量未初始化时,也可以显示初始化。
  • null:用于清空变量的值。
let name = 'yin';
let age = 27;
let isApproved = true;
let firstName = undefined; 
let hobby = null;
dynamic typing

JS是一种动态编程语言。

静态编程语言:当声明变量时需要同时指定变量的类型,类型一旦指定就不能改变,如JAVA

动态编程语言:当声明变量时不需要指定变量的类型,变量类型可以在运行时改变,如python,javascript

可以使用typeof variable查看变量当前的类型.

字符串

对字符串中的引号可以使用\转义;

对双引号可以使用单引号避免转义``

转义字符:

\' '
\" "
\\ backslash
\n new line
\r carriage return
\t tab
\b word boundary
\f form feed

使用+连接字符串

使用+=连接字符串

使用[]获取字符串的字符

JS中字符串string的不可变性

2.3 运算符

2.3.1 算术运算符
+
-
*
/
%
++, --
+=, -=, *=, /*
2.3.2 比较运算符

==作为一种比较操作符equality operator,用于比较两个变量的值是否相等,返回true/false。如果两个变量的类型不一致,会进行隐式类型转换成同一种类型后再进行比较。

1 == true // true
0 == true // false
1 == '1' // true

===作为一种严格的比较操作符strict equality operator,会比较两个变量的类型和值是否相等。与==不同的是,不会进行类型转换。

1 === true // false
1 === '1' // false

!=作为inequality operator,与==的返回值相反,在比较的时候也会进行类型转换。

!==作为``the logical opposite of the strict equality operator,与===`的返回值相反。

>, >=, <, <=

2.3.3 逻辑运算符
  • 或||

    • 针对布尔值,进行逻辑或运算;

    • 针对其他值,将其转化为布尔值再进行计算。(1=true,其他值=false)

    • 寻找第一个真值result = value1 || value2 || value3;

  • 与&&

    • 针对布尔值,进行逻辑与运算
    • 针对非布尔值,将其转化为布尔值再进行计算
    • 寻找第一个假值
  • 非!

    • 将操作数转化成布尔类型,返回相反的值
  • 优先级:非 > 与 > 或

2.4 objects

Reference types包括:object,array,function。定义一个object:

let person = {
    name: 'yin',
    age: 27
};

获取对象中属性的两种方法:

  1. dot notation:person.name
  2. Bracket notation:person['name']

dot notation简单明了,默认使用。

bracket notation在特定的场景下使用,比如属性名是用户的输入或者在程序运行过程中动态得到的,或者属性名中含有空格。

let key = 'name';
let value = 'john'
person[variable] = value;

更新对象中的属性:ourDog.bark = ‘woof’;

给对象中增加属性:ourDog.bark = ‘woof’;

删除对象中的属性:delete ourDog.bark;

遍历对象中的属性:

for (const key in object) {
    if (Object.hasOwnProperty.call(object, key)) {
        const element = object[key];
        console.log(key, element)
    }
}

获取对象中的所有key:Object.keys(object)

判断某个属性是否在对象中:object.hasOwnProperty(propname)

复杂对象:对象中包含对象

获取层级对象中的属性:obj1.obj2.prop

2.5 Arrays

Array is a data structure save a list of items.

let selectedColors = ['red', 'blue'];
console.log(selectedColors);
  • 定义
  • 多维数组
  • 索引
  • push(), pop(), shift(), unshift()
    • push() always add element at the end of the array.
    • pop() always removes the last element of an array.
    • shift() always removes the first element instead of the last.
    • unshift() always add elements in front of the array.

2.6 Functions

A function is basically a set of statements that perform a task or calculates a value.

function greet(firstName, lastName) {
    console.log('Hello ' + firstName + ' ' + lastName);
}

greet('John', 'White');
greet('Mary');

全局作用域:在函数块外部定义的变量具有全局作用域。

不使用let和const定义的变量同样具有全局作用域,应该始终使用let或const定义变量。

本地作用域:在函数内部定义的变量,和函数的参数一起,都只在函数内部生效。

函数内部可以有同名的全局变量和局部变量,局部变量优于全局变量。

2.7 流程控制

2.7.1 Conditional statements

JS中的条件语句包含:if…else和switch…case两种。

2.7.2 Loops

JS中实现循环有以下五种语法:

  • for
let array = ['john', 'mary', 'lucy'];
for (let index = 0; index < array.length; index++) {
    console.log(array[index]);
}
  • for-each
let array = ['john', 'mary', 'lucy'];
array.forEach(element => {
    console.log('hello ' + element);
});
  • while
  • do…while
  • for…in
// for-in
let person = {
    name: 'yin',
    age: 27
};
for (const key in person) {
    if (Object.hasOwnProperty.call(person, key)) {
        const element = person[key];
        console.log(key, element)
    }
}
  • for…of
  • 循环 & 递归:将循环写法修改为递归写法

3. 其他

3.1 随机数

Math.random()返回0-1之间左开右闭的随机数。

Math.floor()向下取整。

生成0-m之间的整数:Math.floor(Math.random() * (m+1));

生成min到max之间的整数:Math.floor(Math.random() * (max - min + 1)) + min

3.2 解析字符串

parseInt(string, radix)函数从字符串string按照radix进制解析一个整数。

3.3 三元表达式

condition ? expression1 : expression2

在expression中可以嵌套三元表达式。

condition1 ? expression1 : condition 2 ? expression2 : expression3

3.4 ES6新特性

var & let:使用var在函数外声明的变量是全局作用域,在函数内声明的变量时局部作用域。

const:不可变对象,避免重新声明,但是对象中的属性是可变的(list中的值,对象中的值)。

如果要避免对象中的值被改变,需要使用Object.freeze(obj)来冻结对象。

4. JS OOP

OOP的四大特性:封装、抽象、继承、多态

对象:key-value对的集合

在JS中没有类这个概念。

创建对象的方式:

  • 直接定义对象(不推荐)
const circle = {
    radius: 1,
    location: {
        x: 1,
        y: 1
    },
    draw: function() {
        console.log("draw a circle");
    }
}
circle.draw();
  • 使用工厂方法创建并构造对象
// factory function
function createCircle(radius) {
    return {
        radius: radius,
        draw: function() {
            console.log("draw a circle");
        }
    }
}

const circle = createCircle(1);
circle.draw();
  • 使用构造方法创建并构造对象
// constructor function
function Circle(radius) {
    this.radius = radius;
    this.draw = function() {
        console.log("draw a circle");
    }
}
let circle = new Circle(1);
circle.draw();

每一个object都有一个构造方法属性,这个方法表明了如何构造该对象。

In javascript, functions are objects

基本类型与引用类型

JS中的数据类型分为基本类型primitive type和引用类型reference type。基本类型复制的是值value,引用类型复制的是引用。

let x = 10;
let y = x;
x = 20; // y = 10
let a = {value: 10};
let b = a;
a.value = 20;
// b: {value: 20}
let number = 10;
function increase(number) {
    number++;
}
increase(number);
console.log(number);// 10
let obj = { value: 10};
function increase(obj) {
    obj.value++;
}

increase(obj);
console.log(obj); // {value: 11}

抽象

隐藏实现细节,只保留必要的接口。

在对象中,使用局部变量来实现对私有属性的隐藏。

function Circle(radius) {
    this.radius = radius; // object property

    let defaultLocation = { x: 0, y: 0 }; // local variable

    let calculateOptimumLocation = function(factor) { // local variable
        // ...
    }

    this.draw = function() { // object method
        calculateOptimumLocation(0.1);
        console.log('draw');
    }
}

Getter/setter

对于对象的public属性和方法来说,可以使用dot notation或bracket notation来获取或者设置value。对于private属性来说,如何实现其getter/setter方法呢?

  • 方法一:手动实现getter/setter方法,通过方法调用获得属性值。
function Circle(radius) {
    this.radius = radius;

    let defaultLocation = { x: 0, y: 0 };

    this.getDefaultLocation = function() {
        return defaultLocation;
    }

    this.draw = function() {
        calculateOptimumLocation(0.1);
        console.log('draw');
    }
}

let circle = new Circle(1);
circle.getDefaultLocation(); // { x: 0, y: 0 }
  • 方法二:基于Object.defineProperty()方法,和public属性一样。
function Circle(radius) {
    this.radius = radius;

    let defaultLocation = { x: 0, y: 0 };

    this.draw = function() {
        calculateOptimumLocation(0.1);
        console.log('draw');
    }

    Object.defineProperty(this, 'defaultLocation', {
        get: function() {
            return defaultLocation;
        }
    })
}

let circle = new Circle(1);
circle.defaultLocation; // { x: 0, y: 0 }

练习

实现一个StopWatch对象,具有以下几个功能:

Start():开始计时;

stop():结束本次计时

duration:返回截止当前为止的计时时长,以秒为单位。

reset():重置计时器

function StopWatch(){

    let status = 'Ready';
    let startTime;
    let duration = 0;
    
    this.start = function() {
        if (status === 'Running') {
            throw new Error('The stopwatch is already running');
        }
        status = 'Running';
        startTime = Date.now();
    }

    this.stop = function() {
        if (status !== 'Running') {
            throw new Error('The stopwatch is not running');
        }
        status = 'Ready';
        duration += ((Date.now() - startTime) / 1000);
        startTime = null;
    }

    this.reset = function() {
        duration = 0;
    }

    Object.defineProperty(this, 'duration', {
        get: function() {
            return duration;
        }
    })
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值