前端开发【第4篇:JavaScript基础】

JavaScript简述

上一篇文章已经聊过JavaScript的历史了这里再也不复述了直接切入正题,JavaScript是一门解释型、动态类型、弱类型语言。javascript

解释型语言和编译型语言就相似看一本书,编译型语言就是直接把整本书给你翻译成中文让你看,效率高。解释型就是给你找一个翻译翻译一句你读一句相对编译型效率就底一些css

动态类型语言:就是一个变量自己的类型不是在定义的时候就指定类型了,而是在在运行的时候动态赋值这个变量是什么类型的语言html

弱类型语言与之对比的就是强类型语言拿Python举例:java

# 定义一个变量
test_value = 1
# 咱们赋值的时候已经指定这个变量为int类型咱们可使用进行int类型的操做
print(test_value + 1)
# 可是若是咱们使用它进行字符串操做就会报错
print(test_value + "str_value")
"""
TypeError: unsupported operand type(s) for +: 'int' and 'str'
"""

强类型语言,如今若是你想用test_value进行字符串操做只能把它转为str类型python

在看一下弱类型的代码JavaScript程序员

let testValue = 1;
// 如今咱们定义一个testValue为int类型并进行int
console.log(testValue + 1);
// 可是现下面的操做
console.log(testValue + "Hello World");
// 如今咱们作字符串的拼接而这时候不须要转换,弱类型有时显得很方便,有时却又极易出错

哦~这里定义变量的时候ECMAScript6之后定义变量var将推出历史舞台改成:let 和const了正则表达式

JavaScript存在方式

看一下HTML和JS的加载顺序编程

1.浏览器加载和渲染html的顺序数组

  1. 浏览器加载和渲染html的顺序
  2. IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的。
  3. 在渲染到页面的某一部分时,其上面的全部部分都已经下载完成(并非说全部相关联的元素都已经下载完)
  4. 若是遇到语义解释性的标签嵌入文件(JS脚本,CSS样式),那么此时IE的下载过程会启用单独链接进行下载。
  5. 而且在下载后进行解析,解析过程当中,中止页面全部往下元素的下载。阻塞加载
  6. 样式表在下载完成后,将和之前下载的全部样式表一块儿进行解析,解析完成后,将对此前全部元素(含之前已经渲染的)从新进行渲染。
  7. JS、CSS中若有重定义,后定义函数将覆盖前定义函数

2. JS的加载浏览器

  1. 不能并行下载和解析(阻塞下载)
  2. 当引用了JS的时候,浏览器发送1个js request就会一直等待该request的返回。由于浏览器须要1个稳定的DOM树结构,而JS中颇有可能有代码直接改变了DOM树结构,好比使用 document.write 或 appendChild,甚至是直接使用的location.href进行跳转,浏览器为了防止出现JS修改DOM树,须要从新构建DOM树的状况,因此 就会阻塞其余的下载和呈现.

3.如何加快HTML页面加载速度

  1. 页面减肥。页面的肥瘦是影响加载速度最重要的因素删除没必要要的空格、注释。将inline的script和css移到外部文件,可使用HTML Tidy来给HTML减肥,还可使用一些压缩工具来给JavaScript减肥
  2. 减小文件数量。减小页面上引用的文件数量能够减小HTTP链接数。许多JavaScript、CSS文件能够合并最好合并,人家财帮子都把本身的JavaScript. functions和Prototype.js合并到一个base.js文件里去了
  3. 减小域名查询。DNS查询和解析域名也是消耗时间的,因此要减小对外部JavaScript、CSS、图片等资源的引用,不一样域名的使用越少越好
  4. 缓存重用数据。使用缓存吧
  5. 优化页面元素加载顺序。首先加载页面最初显示的内容和与之相关的JavaScript和CSS,而后加载DHTML相关的东西,像什么不是最初显示相关的图片、flash、视频等很肥的资源就最后加载
  6. 减小inline JavaScript的数量。浏览器parser会假设inline JavaScript会改变页面结构,因此使用inline JavaScript开销较大,不要使用document.write()这种输出内容的方法,使用现代W3C DOM方法来为现代浏览器处理页面内容
  7. 使用现代CSS和合法的标签。使用现代CSS来减小标签和图像,例如使用现代CSS+文字彻底能够替代一些只有文字的图片,使用合法的标签避免浏览器解析HTML时作“error correction”等操做,还能够被HTML Tidy来给HTML减肥
  8. Chunk your content。不要使用嵌套tables
  9. 指定图像和tables的大小。若是浏览器能够当即决定图像或tables的大小,那么它就能够立刻显示页面而不要从新作一些布局安排的工做,这不只加快了页面的显示,也预防了页面完成加载后布局的一些不当的改变。
  10. 根据用户浏览器明智的选择策略。IE、Firefox、Safari等等等等
  11. 页面结构的例子

4.HTML页面加载和解析流程

  1. 用户输入网址(假设是个html页面,而且是第一次访问),浏览器向服务器发出请求,服务器返回html文件;
  2. 浏览器开始载入html代码,发现<head>标签内有一个<link>标签引用外部CSS文件;
  3. 浏览器又发出CSS文件的请求,服务器返回这个CSS文件;
  4. 浏览器继续载入html中<body>部分的代码,而且CSS文件已经拿到手了,能够开始渲染页面了;
  5. 浏览器在代码中发现一个<img>标签引用了一张图片,向服务器发出请求。此时浏览器不会等到图片下载完,而是继续渲染后面的代码;
  6. 服务器返回图片文件,因为图片占用了必定面积,影响了后面段落的排布,所以浏览器须要回过头来从新渲染这部分代码;
  7. 浏览器发现了一个包含一行Javascript代码的<script>标签,赶快运行它;
  8. Javascript脚本执行了这条语句,它命令浏览器隐藏掉代码中的某个<div> (style.display=”none”)。杯具啊,忽然就少了这么一个元素,浏览器不得不从新渲染这部分代码;
  9. 终于等到了</html>的到来,浏览器泪流满面……
  10. 等等,还没完,用户点了一下界面中的“换肤”按钮,Javascript让浏览器换了一下<link>标签的CSS路径;
  11. 浏览器召集了在座的各位<div><span><ul><li>们,“大伙儿收拾收拾行李,咱得从新来过……”,浏览器向服务器请求了新的CSS文件,从新渲染页面。

5.Yahoo对网页设计性能的建议,我的感受是说得很是好的。

英文版:http://developer.yahoo.com/performance/rules.html

中文翻译:http://www.cnblogs.com/smjack/archive/2009/02/24/1396895.html

原文连接:http://renyongjie668.blog.163.com/blog/static/1600531201097062789/

 

因此咱们建议通常JavaScript代码放在Body最下面,且最好是经过外链式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--CSS样式建议放在head,外部调用-->
    <link type="text/css" rel="stylesheet" href="xiaomi_box/box_css.css">
</head>
<body>

    <!--HTML页面内容    -->

    <!-- 建议放在body最下面,外部调用-->
    <script type="application/javascript" src="4-1.js"></script>
</body>
</html>

JavaScript数据类型

JavaScript数据类型分为两类:原始类型(primitive type)和对象类型(object type)

原始类型:

数字、字符串、布尔值、还有两个特殊的原始值(null[空值]和undefined[未定义])

 

对象类型:

一、普通对象(集合-能够理解为字典且无序)

对象是属性的集合每一个属性都是由"名/值组成"  能够理解为Python中的字典擦~   这个值能够是原始类型的数字、字符串也能够是对象

二、全局对象

有一个特殊的对象Global object

三、数组对象(有序的集合能够理解为列表)

数组(array),有序的集合能够理解为Python中的列表

四、函数对象

首先JavaScript里面没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instance)的区分,全靠一种很奇特的"原型链"(prototype chain)模式,来实现继承。

重要的事情说三遍:JavaScript中没有类和实例的概念他是一个纯面向对象的语言,你能够理解为它的对象是靠一个对象来建立的

网景公司在发明与设计JavaScript的目标,其中很重要的两点:

1. 简易版的Java;

2. 简易,简易仍是简易。

Brendan Eich设计JavaScript的时候引入了Java一个很是重要的概念:一切皆对象。既然JavaScript里面有了对象,那么设不设计继承就是困扰Brendan Eich的一个问题,若是真是要设计一个简易的语言其实能够不要继承机制,继承属于专业的程序员,可是JavaScript里那么多的对象,若是没有一种机制,他们之间将如何联系了,这必然会对编写程序的可靠性带来很大的问题,可是引入了继承又会使用JavaScript变成了完整的面向对象的语言,从而提升了它的门槛,让不少初学者望而却步,折中之下,Brendan Eich仍是选择设计继承,但毫不是标准的继承(说道这里我想起了一样使用EMCAScript标准设计的语言ActionScript,它里面就有很完整的继承,作起来很惬意,我常想这是否是JavaScript之后的趋势,说不定哪天JavaScript会变的搄更完美写了?)。折中是指Brendan Eich不打算引入类(class),这样JavaScript至少看起来不像面向对象的语言了,那么初学者就不会望而却步了(这是欺骗啊,进来后倒腾死你,这就是所谓的关门打狗了,并且如今不仍是引入了class吗,可是这个class实际仍是调用了原型链)。

Brendan Eich思考以后,决定借鉴C++和java的new命令,将new命令引入了JavaScript,在传统的面向对象的语言里,new 用来构造实例对象,new 会调用构造函数,可是传统面向对象的语言new 后面的是类,内部机制是调用构造函数(constructor),而Brendan Eich简化了这个操做,在JavaScript里面,new 后面直接是构造函数,如是咱们能够这么写一个Person类:

        function Person(name) {
            this.name = name
        }
        let personOne = new Person("Brendan Eich");
        console.log(personOne.name)

这样就建立了一个新的实例了。可是new有缺陷。用构造函数生成实例对象是没法没法共享属性和方法,例以下面代码:

        function Person(name) {
            this.name = name;
            this.nation = 'USA';
        }
        let person1 = new Person("Brendan Eich");
        let preson2 = new Person("Shuai Ge");

        person1.nation = "China";

        console.log(person1.nation);  // China
        console.log(preson2.nation);  // USA

每个实例对象,都有本身的属性和方法的副本。这不只没法作到数据共享,也是极大的资源浪费。和JavaScript工厂模式的缺点同样,过多重复的对象会使得浏览器速度缓慢,形成资源的极大的浪费。

考虑到这一点,Brendan Eich决定为构造函数设置一个prototype属性,这个属性都是指向一个prototype对象。下面一句话很重要:全部实例对象须要共享的属性和方法,都放在这个Prototype对象(原型对象)里面;那些不须要共享的属性和方法,就放在构造函数里面

实例对象一旦建立,将自动引用prototype对象的属性和方法。也就是说,实例对象的属性和方法,分红两种,一种是本地的,另外一种是引用的。如是咱们能够改写下上面的程序:

        function Person(name) {
            this.name = name;
        }
        // 咱们不须要指定prototype对象当咱们建立对象的时候默认会生成
        Person.prototype = {nation: "USA"};

        let person1 = new Person("Brendan Eich");
        let person2 = new Person("Shuai Ge");
        
        console.log(person1.nation);
        console.log(person2.nation);

当咱们这样写程序时候Person.prototype.nation = 'China'; 全部实例化的类的nation都会变成China。

因为全部的实例对象共享同一个prototype对象,那么从外界看起来,prototype对象就好像是实例对象的原型,而实例对象则好像"继承"了prototype对象同样。prototype只是提供了实现JavaScript继承的一个很方便的途径和手段。

五、日期、正则、错误 三种有用的对象

从字面上就能够看出日期是就表明日期的对象,正则表达式对象,还有就是定义了错误的对象

 

总结一下就是:数字、字符串、布尔值、null、undefined、对象(集合-字典)、数组(列表)、函数、日期、正则、错误这些对象类型,记住一切皆对象

 

 数字类型

一、JavaScript中的数字是不区分整数和浮点数的,它们默认都是采用浮点数展现

默认ES5是支持16进制的,可是不支持8进制,在ES6中明确了二进制采用[0b或0B],8机制采用[0o或0O]表示

二、数字的+、-、*、/、加减乘除

这些复杂的运算符都是经过Math对象属性定义的函数和常量实现的

三、二进制浮点数和四舍五入偏差

首先要明确一点在计算机的世界里计算机只是别0,1,咱们平时看到的任何 在计算机的理解力都是0,1,只是在咱们看前作了一个转换,有了这个前提咱们来看下

console.log(0.1 + 0.2 )
// 0.30000000000000004

what's FK ~ 什么鬼?JavaScript采用了IEEE-754表示法基本上现代编程语言都采用的是这个,你觉得其余语言就会是对的吗?天真你试试~~

缘由是:

那么0.1和0.2转换成二进制分别是,
 
(0.1) => 0.0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 101
(0.2) => 0.0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 01
而后对上面的两个二进制数字作加法,获得的结果是,
 
0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1101 01
再把这个二进制转换成十进制,就是咱们前面的结果0.30000000000000004了

有写语言没有这个问题说明本质上对其作了封装~

ES6中也没有对其进行封装只提供了一个偏差值~~!

那咱们应该如何解决这个问题呢?两种方法:

变大求值

咱们把float值放大N倍后为正数在进行计算

let a = 0.1;
let b = 0.2;
let ret = (a * 10 + b * 10) / 10;
console.log(ret);

字符串求值

let a = 0.1;
let b = 0.2;

let ret = (a + b).toFixed(1);
let newRet = parseFloat(ret);
console.log(newRet);

日期类型

JavaScript语言核心包括Date()构造函数,用来建立表示日期和时间对象。这些日期对想的方法为计算提供了简单的API

let beforDate = new Date(2011, 0, 1);  // 2011年1月1日
let laterDate = new Date(2011, 0, 1, 17, 10, 30);  //同一天,当地时间5:10:30pm
let nowDate = new Date();  // 当前日期和时间

let elapsed = nowDate - laterDate;  //日期减法: 计算时间检核的毫秒数

laterDate.getFullYear();  // ==> 2011 获取年份
laterDate.getMonth();  // ==> 0 获取从0计数的月份
laterDate.getDay();  // ==> 5 获得星期几,0表明星期日,5表明星期一
laterDate.getHours();  // ==> 17:5pm 当地时间
laterDate.getUTCHours();  // 使用UTC表示小时的时间,基于时区

还有不少方法能够查看文档

字符串

字符串和Python中的字符串差很少ES6中增强了Unicode表示法,只要将码点放入大括号,就能正确解读该字符。

"\u{20BB7}"
// "𠮷"

"\u{41}\u{42}\u{43}"
// "ABC"

let hello = 123;
hell\u{6F} // 123

'\u{1F680}' === '\uD83D\uDE80'
// true

JavaScript的字符串和Python中的字符串操做有不少类似之处也仅限于类似。

let s = 'hello world';  // 建议JavaScript字符串使用单引号由于在HTML中CSS样式类的应用是使用双引号的
s.charAt(0);            // ==> 'h' 第一个字符
s.charAt(s.length-1);   // ==> 'd' 最后一个字符
s.substring(1, 4);      // ==> 获取第1~4个字符相似列表切片
s.slice(1, 4);          // ==> 同上
s.slice(-3);            // ==> 'rld' 最后三个字符
s.indexOf('l');         // ==> '2' 获取字符第一次出现的位置
s.split(',');           // ==> 分割成数组
s.replace('h', 'H');    // ==> 'Hello World' 全文字符替换
s.toUpperCase();        // ==> 'HELLO WORLD' 转为为答谢

一样和Python中同样字符串是只读的若是想修改,只能新建一个新的

JavaScript能够理解为只读数组也能够用数组的部分功能好比s[0]下标~~

而且JavaScript自己支持正则匹配功能~

let text = 'testing: 1, 2, 3';  // 文本示例
let pattern  = /\d+/g;  // 匹配全部包含一个或多个数字的实例
pattern.test(text);  // 首先pattern定义了一个匹配方法,而后匹配的字符是text而后返回结果 基本上全部语言的匹配都大同小异

text.search(pattern);  // ==> 9 首次匹配成功的位置
text.match(pattern);   // ==> ["1", "2", "3"] 全部匹配组成的数组
text.replace(pattern, "#");  // ==> 'testing: #, #, #'
text.split(/\D+/);  // ==> ["", "1", "2", "3"] 用非数字字符截取字符串

 布尔值

True 或者False和Python中同样

null和undefind

null

JavaScript中的null它表示一个特殊值,经常使用来描述“空值”。null在javaScript中也是一个特殊的对象,它能够表示数字、字符串、对象是无值的

undefind

JavaScript还有第二个值来表示值的空缺,可是他表示更深层次的空值,表示变量未初始化或者未定义

 

undefind通常能够理解为出乎意料的的系统级别的空值,而null表示正常的意料中的空值,虽然它俩不一样可是大多状况下能够互换的,可是在定义变量或者传参的时候建议使用null

 

全局对象

在原始类型和对象类型中,对象类型有个很是重要的对象:全局对象  全局对象定义的属性是全局定义的符号,JavaScript能够直接调用

 

JavaScript解释器启动的时候(或者页面浏览器加载新页面的时候),它将建立一个新的全局对象,并给它一组定义的初始属性

  • 全局属性:好比undefind、Infinity、NaN
  • 全局函数:好比isNaN、parseInt()、eval()
  • 构造函数:好比Date()、RegExp()、String()、object()、和Array
  • 全局对象:好比Math和JSON

客户端window对象额外定义了一些全局对象,而且在代码最顶级-不在任何函数的JavaScript能够经过this关键字引用let global = this;

包装对象

JavaScript对象是一种复合值:他是属性或已命名值的集合经过 “.”【点】来调用属性值,当属性值是一个函数的时候称其为“方法”

咱们来看下面一个例子:

let s = 'hello world';
s.substring(1,4)

在JavaScript中字符串不是一个对象那为何他又属性和方法呢?

本质是:字符串在调用属性的时候会将字符串的值经过调用new string(s)的方式转换为对象,一旦引用结束就个被建立的对象就被销毁(其实在实现上并不必定销毁这个临时对象,整个过程看起来是这个样子)个人天啊~~

包括数字、和布尔值都是同理~  Number()或Boolean

"==" 等于运算将原始值和包装对象视为相等,单“===”全等运算将它们视为不等

不可变原始值和可变的对象引用

JavaScript中原始值(字符串、数字、null、undefind、布尔值)与对象(包括数组和函数)有本质的区别,原始值不能够修改好比9这个数你怎么改为其余值这自己就说不通9就是9他不能修改

 字符串就不太明显了,能够用Python的理解,一样不能够修改,字符串是一段连续的内存地址

 

对于对象来讲他们是可变的可修改的,而且即便两个对象的属性及其相同的值他们也是不相等的,各索引元素彻底相等的两个数组也不相同

let arrayA1 = [1, 2, 3, 4]
let arrayB1 = [1, 2, 3, 4]
arrayA1 == arrayB1
false

我擦这是什么鬼?这个咱们能够理解为咱们建立了两个对象在内存中,两个不一样的内存地址怎么能相等呢?我觉的JavaScript在这里更精准些

咱们一般将对象称为引用类型(reference type) 今后来和JavaScript的类型区分开,依照术语对象之都是引用,这个“引用能够理解为对内存地址的引用”

let arrayA = [];  //定义一个空的数组对象
let arrayB = arrayA;  // 把arrayA的值赋值为arrayB
arrayA[0] = 1;  //给arrayA里加一个元素由于A和B一样指向的是一块内存因此B也随之修改
arrayA === arrayB
true

上面是铁则化简就是:只有两个值引用的内存地址相同才相等

因此若是引用同一个内存地址那么一个值修改的时候另外一个值将一样修改,有时候你只想复制一份能够经过循环来取

a = [1, 2, 3, 4, 5, 'hello']
b = []
for(let i = 0; i <a.length; i++){ b[i] = a[i]}

复制完也是不一样的由于两个是不一样的对象须要注意

类型转换

这个里面须要注意的是:

相等性:

null == undefind 是相等的  

"0" == 0 在比较以前将字符串转换为数字

0 == false  比较以前将布尔值转换为数字

“0” == false 在比较前将布尔值和字符串转化为数字

显示类型转换

除了布尔值和undefind以外的任何值都具备toString()方法这个方法一般和string()方法返回结果一致

// 二进制转换
let n = 17

binary_string = n.toString(2)  //转换为二进制
octal_string = "0" + n.toString(8) //转化为8进制
hex_string = "0x" + n.toString(16)  //转化为16进制

对象转换为原始值

({x: 1, x2: 2}).toString()
"[object Object]"
[1, 2, 3].toString()
"1,2,3"
(function(x){f(x);}).toString()
"function (x){f(x);}"
/\d+/g.toString()
"/\d+/g"
new Date(2017,9,12).toString()
"Thu Oct 12 2017 00:00:00 GMT+0800 (中国标准时间)"

这个结果颇有意思~~

JavaScript对象到字符串转化的过程以下:

一、首先判断是否有toString()方法若是他返回一个原始值将这个值转化为字符串返回

二、若是没有toString()方法或者返回的不是一个原始值则调用则掉用valueOf()方法,若是存在这个方法则调用它,若是返回的是原始值则转化为字符串

三、不然javaScript没法从toString()或valueOf()方法中得到一个原始值则抛出异常

在对象到数字的过程当中作了以下操做

一、若是对象存在valueOf()方法调用他若是返回一个原始值将这个原始值转换为数字(若是须要的话)而后返回数字

二、不然若是具备toString()方法,后者返回一个原始值JavaScript将它转换并返回

三、异常

对象转换为数字的细节解释了为何 空数组会被转化为数字0数组默认继承了valueOf()这个方法返回一个对象在调用toString()方法转换为空字符,空字符在转化为数字,JavaScript “+”和“==”若是一个是对象JavaScript会将方法转化为原始值而不是其余素数运算符的方法执行对象到数字的转换

日期的状况比较特殊它是JavaScript语言核心惟一的预先定义类型,他定义了有意义的到字符串和数字的转换经过valueOf或toString()返回原始值将被直接使用而不是强制转换为数字或字符串

函数做用域及声明

let块级做用于

ES6 新增了let命令,用来声明变量。它的用法相似于var,可是所声明的变量,只在let命令所在的代码块内有效。

{
  let a = 10;
  var b = 1;
}

a // ReferenceError: a is not defined.
b // 1

因此for循环很适合let

for (let i = 0; i < 10; i++) {
  // ...
}

console.log(i);
// ReferenceError: i is not defined

上面代码中,计数器i只在for循环体内有效,在循环体外引用就会报错。

下面的代码若是使用var,最后输出的是10

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10

上面代码中,变量ivar命令声明的,在全局范围内都有效,因此全局只有一个变量i。每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,全部数组a的成员里面的i,指向的都是同一个i,致使运行时输出的是最后一轮的i的值,也就是10。

若是使用let,声明的变量仅在块级做用域内有效,最后输出的是6。

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6

不容许使用提早

在ES5咱们调用1个变量的时候若是他没有声明默认是undefind,如今不能够了没有声明的变量不容许使用

暂时性死区

只要块级做用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,再也不受外部的影响。

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

这里也觉得typeof将不是一个安全操做由于它会触发异常了若是变量没有声明

不容许重复声明在相同做用于块内

function func(arg) {
  let arg; // 报错
}

function func(arg) {
  {
    let arg; // 不报错
  }
}

为何要引入块级做用域?

ES5 只有全局做用域和函数做用域,没有块级做用域,这带来不少不合理的场景。

第一种场景,内层变量可能会覆盖外层变量。

var tmp = new Date();

function f() {
  console.log(tmp);
  if (false) {
    var tmp = 'hello world';
  }
}

f(); // undefined

上面代码的原意是,if代码块的外部使用外层的tmp变量,内部使用内层的tmp变量。可是,函数f执行后,输出结果为undefined,缘由在于变量提高,致使内层的tmp变量覆盖了外层的tmp变量。

第二种场景,用来计数的循环变量泄露为全局变量。

var s = 'hello';

for (var i = 0; i < s.length; i++) {
  console.log(s[i]);
}

console.log(i); // 5

const声明一个只读的常量。一旦声明,常量的值就不能改变。
这意味着这个常量一旦声明就必须马上赋值之后不容许修改

ES6中有了块级做用域,JavaScript的做用域链基本上和Python的做用域类似了  全局和局部做用域

特殊的是块级做用于的暂时性死区

表达式和运算符

直接定义原始类型也就是直接声明 

let a = 1;
let b = "hello"
let c = null
let d;  // undefind

对象和数组的初始化表达式也就是直接声明对象和数组

let a = {}
let b =[]

函数定义表达式也就是声明一个函数

let function a { console.log("Hello World~ ")}

属性的访问

普通对象{} 能够经过.或者对象[‘key’]来进行访问,数组对象的话能够相似python的列表访问方式

若是属性对应的值是一个方法的话能够加()执行

对象建立表达式

let a = new Object()

加、减、乘、除、位运算

“==”和“===”相等和不等运算

== 和 ===  、   == 为宽松的判断是否相等, === 为严格的判断是否相等, === 在判断的时候不会作类型的转换!!!

他是如何严格判断的呢?

  • 若是两个值类型不相同则不相等
  • 若是两个值都是null或者都是undefind它们不相等
  • 若是两个值都是布尔值true或者false它们相等
  • 其中一个是NaN或者两个值都是NaN则它们不相等,NaN和其余任何值都不相等包括它自己,由于NaN自己是“无心义”
  • 若是两个值为数字且相等则它们相等,若是一个为0另外一个为-0则也相等
  • 若是为字符串且对应16位数彻底相等则它们相等
  • 若是两个引用值指向了同一个对象、数组、或函数则它们相等

不严格的==是如何判断的?

一、若是两个操做数类型相等,那么就相似严格相等

2.、若是操做两个数类型不一样可能相等:

  • undefind和null相等字符串
  • 数字比较对边进行类型转换后进行比较
  • 若是其种一个值是true转换为1比较,若是其中一个是false转换为0比较
  • 若是一个是对象,另外一个是字符串转换后比较
  • 其余类型之间比较均不相等

比较运算符相似==可能会进行类型转换

 

instancefo相似Python中的isinstance

let nowDate = new Date()
undefined
nowDate instanceof Date
true

Python的是

print(isinstance(11, int))

条件运算符JavaScript惟一一个三元运算符 ?

表达式: bool ? true: false   解释:问号前面为判断式,若是为真用 冒号前的true对应的表达式值计算而后返回,不然用冒号后面的false表达式计算并返回

// username须要提早定义ES6已经不容许未定义使用了
greeting = "hello" + ( username ? username : "there")
// 等价于

let greeting = "hello";

if (username){
    console.log(greeting + username);
}else{
    console.log(greeting + "there");
}

其余运算符

一、typeof获取类型

二、delete删除属性和python中的相似

三、逗号运算符哈哈

逗号运算符是二元运算符,它的操做数能够是任意类型。它首先计算左操做数,而后计算右操做数,最后返回右操做数的值,看下面的代码

i = 0, j = 1, k = 2
// 最后返回的结果是 2,它和线面的代码基本上是等价的
i = 0; j = 1; k =2

用在哪里?

// for循环中的第一个逗号是第let语句的一部分
// 第二个逗号是逗号运算符
// 它将两个表达式(i++和j--)放在一条for循环中
for(let i = 0, j = 10; i <j ; i++, j--){
    console.log(i + j)
}
相关文章
相关标签/搜索