​前端教学讲义:JS基础

2018-07-13 admin

讲义内容:JS 诞生的背景、基本类型、运算符

以下内容只涉及 ES5 标准,ES6 增加的新内容可以在网上查找到。

JS 诞生的背景

上世纪 90 年代网景公司开发的浏览器独步天下

一个叫做 Brendan Eich 的工程师受命于开发一款脚本语言,来增强浏览器的功能。

这名工程师花费了 10 天时间设计出了第一个版本,名叫 LiveScript。

后来因为当时 Java 正红,公司将其改名为 JavaScript,所以 JS 和 Java 其实什么关系。

这名工程师在设计语言之初有几个目标

  • 简单易用,不需要专业的计算机知识就能使用
  • 因为个人的喜爱,所以增加对函数式编程的支持
  • 因为公司压力,所以也要支持面向对象

后来 JS 因为市场认同,打败了 VBScript,Java plugin 等一系列增强浏览器的方案,成了事实标准。

网景公司倒闭之后,JS 的标准制定有 ECMA(欧洲电脑制造商协会)制定,所以又叫做 ECMAScript, 新的标准叫做 ES6、ES7、ES2018 … 每年会收集各种语言规范建议,通过 草案、stage1、stage2 等几个阶段,并在浏览器中有实现后会成为正式标准。

所以 JS 具有以下特点:

  • 向下兼容,包括兼容 bug(typeof null,大数)
  • 奇怪、蹩脚的规范,从技术上来说缺点很多
  • 运用场景广泛
  • 迭代速度快,

会在项目里使用还在草案阶段的新语法

变种、超集、子集 很多(coffee script, typescript, Action Script, flow, AssembleScript)

基本类型

JS 中的基本类型有以下几种:

  • undefined
  • null
  • Boolean
  • Number
  • String
  • Function
  • Array
  • Object

和 Java 一样,所有类型都是基于 Object(除了 undefined ?)

通过 「var」关键字声明一个变量,方法和大多数语言一样。

JS 是动态语言,变量不用区分类型,不同类型之间的变量可以相互赋值。

var foo = 1;
var bar;
var a, b, c;
bar = foo = “abcd”
undefined 和 null

当一个值没有初始值的时候,默认值为 undefined。

undefined 在 JS 中是个语言设计的缺陷例子。

undefined 的行为在大多数情况下和 null 一样,都是不可访问的值,但是在 typeof 的时候结果不同

var und;
var nl = null;
typeof und === ’undefined’
typeof nl == ‘object’

数字

Boolean, Number,String 的行为和大多数语言一样。

可以直接声明也可以通过构造函数、工厂模式声明,三者没什么区别。

var a = 123
var a = new Number(123)
var a = Number(123)

在 JS 中 数字的取值范围是 -253 - 1 到 253 - 1,范围小于 long 型,并且计算时有精度问题

1.2 / 0.2
// 5.999999999999999

声明数字的方式和其它语言类似,科学计数法、八进制、十六进制

var a = 1e3
// 1000
var a = 0o12
// 10
var a = 0xa
// 10

通过 「toString」方法可以转换成字符串,并设置进制

var a = 1000
a.toString(10)
// “1000”
a.toString(8)
// “1750”
a.toString(16)
// “3e8”

在 JS 中,有两个特殊的数字,NaN 和 Infinity。

当字符串或者其他类型转换成数字失败的时候,就会返回 NaN,但是 NaN 的类型依然是 number。

NaN 和任何数字计算后,结果都是 NaN。

当数字除以 0 的时候,就会返回 Infinity。

Number(undefined)
// NaN
Number(null) // 我也很费解,为什么 null 转换成数字就是 0
// 0 
Number("asdf")
// NaN
10 / 0
//Infinity

字符串

在 JS 中字符串是可变长,而且可以通过 「+」 操作符做拼接。

字符串在内容中应该是双字节储存,可以通过索引访问每个字符,而不是每个 byte。

在浏览器中编码格式根据网页的编码格式而设置(在 node 中默认是 UTF8?)

在 JS 中,声明一个字符串通过单引号或者双引号都可以,二者没有区别。通常习惯是通过单引号访问,因为可以少按一个 shift。

var a = ‘123’
var b = “123”
a == b
a[0]  // 通过索引访问的结果仍然是个字符串
// “1”

函数

函数在 JS 中是一等公民,可以赋值给变量,有两种声明方式

function plus(a, b) { return a + b}
var plus = function(a, b) { return a + b }

第二种方法其实是将一个「匿名函数」复制给了变量 plus。

这两种方式在使用上没太大区别,除了在「声明前置」的场景下会有点区别

匿名函数还有一种方法叫做「立即执行函数」。

(function(a, b){ return a + b })(10, 20)
// 30

函数只会将 return 声明的表达式的值返回出去,在函数没有声明 return 的时候,默认返回 undefined

function plus (a, b) { a + b }
plus(1, 2)
// undefined

函数和作用域 函数和变量一样,可以在任何地方声明、使用,

每个函数独立出了一个作用域,作用域可以互相嵌套。

函数作为一个变量,本身也在父作用域下

function foo(b) {
    var a = 10
    // 这里属于 foo 的作用域,内部有 bar, b, a 三个变量
    function bar() {
        var c = 20;
        return a + b + c // 这里属于 bar 的作用域,因为在 foo 之内,所以可以访问 a 和 b
    }
    // 这里不能访问 c
    return bar();
}

由于 JS 在设计的时候,怕用户不理解变量需要先声明再使用,所以对变量会有「声明前置」,帮助大家提前声明所需要的变量。

下面我们用立即执行函数创建一个闭包来解释什么叫「声明前置」

(function() {
    console.log(fn, foo);
    function fn(a, b){ return a + b };
    var foo = 1234;
    console.log(fn, foo);
})()
// function (a, b){ return a + b } undefined
// function (a, b){ return a + b } 1234

上面的代码相当于:

(function() {
    function fn(a, b){ return a + b };
    var foo;
    console.log(fn, foo);•
    foo = 1234;
    console.log(fn, foo);
})()

如果我们用匿名函数赋值给一个变量,那么会有下面效果:

(function() {
    console.log(fn, foo);
    var fn = function(a, b){ return a + b };
    var foo = 1234;
    console.log(fn, foo);
})()

// undefined undefined
// function (a, b){ return a + b } 1234

上面的代码相当于:

(function() {
    var fn, foo;
    console.log(fn, foo);
    fn = function(a, b) { return a + b};
    foo = 1234;
    console.log(fn, foo);
})()

数组

在 JS 中数组是可变的,而且数组内可以放任何值。

数组的长度是最后一个元素的索引加一。

如果访问没有设置的元素,将会返回 unfined

var array = [];
array[0] = 1;
array[2] = “1234”;
array[4] = function(){};
// [1, undefined, “1234”, function(){}]
array[1]
// undefined

js 数组中自带了很多方法,方便我们对数组做操作,比如说 map, reduce 等等

[1, 2, 3].map(function(d) { return d + 1 })
// [2, 3, 4]
[1, 2, 3].reduce(function(r, d) { return r + d }, 0)
// 6

如果想要删除数组中的某个元素的话,我们可以用 delete 关键词,或者直接将索引的位置设置成 undefined

var array = [1, 2, 3]
delete array[1]
// [1, undefined, 3]

如果我们需要删除数组中某个元素,并且缩短数组长度的话,就需要用到 splice。

var array = [1, 2, 3]
array.splice(1, 1)
console.log(array)
// [1, 3]

一些常用的数组方法还有 slice, forEach, find, every, includes 等等

对象

和 java 一样,对象(Object) 是所有类型的基类。它相当于 JSON 里的键值对结构体,可以动态的挂载任何属性。

声明的方法有两种,{} 和 new

var a = {}
var b = new Object()
a.num = 1
a.str = "1234"
console.log(a)
// { num: 1, str: "1234"}

对象(Object)有点类似 Java 里的 HashMap,但 Key 只能是字符串。可以通过类似数组索引的方式来访问对象上的键。

这种方法和点操作符是一样的效果,当键名由一些特殊的字符组成的时候,我们可以通过索引方式访问。

var obj = {value: 1234}
console.log(obj["value"])
// 1234

这样声明或者访问会报错:

var obj = { some-value: 1234 }
obj.some-value

我们需要让编译器知道 some-value 是一个键名,所以需要将它们用引号括起来

var obj = { "some-value": 1234 }
obj["some-value"]

当一个对象中挂载了一个函数,在函数中可以通过 this 来访问对象内的其他属性,this 也可以理解为「执行上下文」

function fn () { console.log(this.value) }
var obj = { fn: fn, value: 1234 }
obj.fn() // 此时 fn 的执行上下文就是 obj
// 1234

var otherObj = { fn: fn, value: "abcd"}
otherObj.fn() // 此时 fn 的执行上下文就是 otherObj
// "abcd"

由于函数和数组是所有类型的基类,所以可以像对象一样随意的扩展属性。

但是字面量(如数字、布尔值、字符串、null、undefined) 是不能随意扩展的。

function plus(a, b) { return a + b}
plus.value = 1234
plus(12, plus.value)
// 1246

var array = []
array.value = 1234
console.log(array.value)
// 1234

var a = true;
a.value = 1234
console.log(a.value)
// undefined

运算符

JS 的运算符和其他语言基本类似,就±*%/这些,外加一些二进制操作符。

但因为 JS 弱类型的特性,有些场景是其他语言没有的,比如一个数字加一个字符串,结果是什么?

1+"2"
// "12"

这种场景还可以理解,数字和字符串相加的时候,数字通过调用 toString 被转换成了字符串。

1 + {}
// "1[object Object]"

数字和对象相加的时候,对象和数字都调用了 toString,被转换成了字符串

{} + []
// 0

但是空对象和空数组相加结果却是 0,我也不知道为什么

var obj = {}
if (obj) console.log("obj is true")
// "obj is true"

obj == true
// false

上面这个例子中,obj 是个空对象,在 if 条件判断中被当作真值,但是和 true 对比的时候却返回 false。

JS 的隐式转换规则很诡异,很多都是为了兼容早期版本中错误的实现,这里没必要细究转换规则是什么。

我们只需要记住以后用严格相等符(===)作对比,避免不同类型的变量相互运算。

"1" == 1
// true

"1" === 1
// false

循环

JS 的循环和其它类似,也都是 for, do…while 这种写法。

但是,我们一般不用 for 作循环,而是用数组方法 forEach,map(因为 for 写起来很麻烦,而且还需要单独声明一个变量)

[1, 2, 3].forEach(function(value) {
  return value + 1;
})
// [2, 3, 4]

另外还可以通过 for…in 来遍历一个对象

var obj = {a:1, b:2, c: 3}
for (var key in obj) {
  console.log(key)
}
// "a"
// "b"
// "c"

但我们一般也不这么用,而是用 Object.keys 取得包含对象所有键的数组

var obj = {a:1, b:2, c: 3}
Object.keys(obj)
// ["a", "b", "c"]

Object.keys(obj).forEach(console.log)
// "a"
// "b"
// "c"

课后习题

第一题:JS 的运用领域都有哪些,作为弱类型的语言执行效率如何,为什么?

第二题:typeof 关键字的返回值有几种结果?

第三题:下面两种写法有什么区别

{
  0: "a",
  1: "b",
  2: "c"
}

["a","b","c"]

第四题:下面代码的运行时会不会报错,this 指向哪里?

function fn () { console.log(this.value) }
fn()

第五题:声明的变量是如何被回收的

原文链接:https://segmentfault.com/a/1190000015620727

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-35878.html

文章标题:​前端教学讲义:JS基础

相关文章
从2014年的发展来展望JS的未来将会如何
<font face="寰�杞�闆呴粦, Arial, sans-serif ">2014骞达紝杞�浠惰�屼笟鍙戝睍杩呴€燂紝鍚勭�嶈��瑷€灞傚嚭涓嶇┓锛屼互婊¤冻鐢ㄦ埛涓嶆柇鍙樺寲鐨勯渶姹傘€傝繖浜涜��...
2015-11-12
Vue.js组件tab实现选项卡切换
本文实例为大家分享了vue插件tab选项卡的具体代码,供大家参考,具体内容如下 效果图: 代码如下: <!DOCTYPE html> <html lang="en"> <head> ...
2017-03-13
破解前端面试(80% 应聘者不及格系列):从 闭包说起
不起眼的开始 招聘前端工程师,尤其是中高级前端工程师,扎实的 JS 基础绝对是必要条件,基础不扎实的工程师在面对前端开发中的各种问题时大概率会束手无策。在考察候选人 JS 基础的时候,我经常会提供下面这段代码,然后让候选人分析它实际运行的结...
2017-06-02
JavaScript教程:JS中的原型
Keith Peters 几年前发表的一篇博文,关于学习没有“new”的世界,其中解释了使用原型继承代替构造函数。两者都是纯粹的原型编码。 标准方法(The Standard Way) 一直以来,我们学习的在 JavaScript 里创建对...
2015-11-12
three.js实现围绕某物体旋转
话不多说,请看代码: 可以拖动右上角观察变化 <!DOCTYPE html> <html lang="en" style="width: 100%; height:100%;"&gt...
2017-02-17
NodeJS参考手册pdf版
下载地址:Nodejs参考手册PDF版下载 ...
2015-11-12
前端交流QQ群
我们建立了一个前端交流QQ群供大家交流,有什么问题都可以在群里提问,欢迎你的加入,也希望我们大家能够在群里互帮互助,同时也能学到东西。 我们相信,前端有你更精彩! 为了让更多的小伙伴加入我们,欢迎大家转发扩散! 长按以上二维码加入我们 ...
2016-04-01
Node.js学习(1)----HTTP服务器与客户端
Node.js 标准库提供了 http 模块,其中封装了一个高效的 HTTP 服务器和一个简易的HTTP 客户端。http.Server 是一个基于事件的 HTTP 服务器,它的核心由 Node.js 下层 C++部分实现,而接口由 Jav...
2015-11-12
Riot.js:不足1KB的MVP客户端框架
Riot.js是一款MVP(模型-视图-呈现)开源客户端框架,其最大的特点就是体积非常小,不足1KB,虽然体积小,但它可以帮助用户构建大规模的Web应用程序。 Riot.js是由Moot公司开发,目前最新版本为v0.9.2,遵循MIT开源许...
2016-03-11
2014年最流行前端开发框架对比评测
如今,各种开发框架层出不穷,各有千秋。哪些是去年较受开发者关注的呢?前不久,云适配根据Github上的流行程度整理了2014年最受欢迎的6个前端开发框架,并进行对比说明,希望帮助有需要的朋友选择合适自己的前端框架。 1. Bootstrap...
2015-11-12
回到顶部