javascript高级程序设计 基础语法

1.基础语法

1.1变量

1.1.1 var的使用

声明

使用 var 操作符(注意 var 是一个关键字),后跟变量名,它保存任何类型的值(不初始化的情况下,变 量会保存一个特殊值 undefined)。使用var不仅可以改变变量保存的值,也可以改变值的类型

作用域

使用 var 在一个函数内部定义一个变量,就意味着该变量将在函数退出时被销毁

function test() { 
 var message = "hi"; // 局部变量
} 
test(); 
console.log(message); // 出错!

不过,在函数内定义变量时省 略 var 操作符,可以创建一个全局变量,只要调用一次函数 test(),就会定义 这个变量,并且可以在函数外部访问到

function test() { 
 message = "hi"; // 全局变量
} 
test(); 
console.log(message); // "hi" 
var声明提升(仅var有,let、const没有)

“提升”(hoist),也就是把所有变量声明都拉到函数作用域的顶部。使用这个关键字声明的变量会自动提升到函数作用域顶部,if、for不属于函数作用域

function foo() { 
 console.log(age); 
 var age = 26;//var会被提升到函数作用域顶部 
} 
foo(); // undefined 
//代码等同于
function foo() { 
 var age; 
 console.log(age); 
 age = 26; 
} 
foo(); // undefined 

使用var声明同一个变量也没有问题。

1.1.2 let的使用

声明

let 跟 var 的作用差不多,但有着非常重要的区别。最明显的区别是,let 声明的范围是块作用域, 而 var 声明的范围是函数作用域。

let声明仅在块作用域中有效,例如 if for { }中,

if (true) { 
 let age = 26; 
 console.log(age); // 26 
} 
//块作用域外部
console.log(age); // ReferenceError: age 没有定义
//不同作用域之间
let age = 30; 
console.log(age); // 30 
if (true) { 
 let age = 26; 
 console.log(age); // 26 
}

let 也不允许同一个块作用域中出现冗余声明。对声明冗余报错不会因混用 let 和 var 而受影响。用var和let声明同一个变量名会报错

暂时性死区

let 与 var 的另一个重要的区别,就是 let 声明的变量不会在作用域中被提升。

// name 会被提升
console.log(name); // undefined 
var name = 'Matt'; 
// age 不会被提升
console.log(age); // ReferenceError:age 没有定义
let age = 26; 
全局变量

与 var 关键字不同,使用 let 在全局作用域中声明的变量不会成为 window 对象的属性(var 声 明的变量则会)。

let依旧可以声明成为全局变量,只是在顶层对象window中不存在,区分var使用

var name = 'Matt'; 
console.log(window.name); // 'Matt' 
let age = 26; 
console.log(window.age); // undefined 
for循环中的使用

在使用 var 的时候,最常见的问题就是对迭代变量的奇特声明和修改:

for (var i = 0; i < 5; ++i) { 
 setTimeout(() => console.log(i), 0) 
} 
// 你可能以为会输出 0、1、2、3、4 
// 实际上会输出 5、5、5、5、5 

之所以会这样,是因为在退出循环时,迭代变量保存的是导致循环退出的值:5。在之后执行超时 逻辑时,所有的 i 都是同一个变量,因而输出的都是同一个最终值。Javascript引擎是在执行完for循环后再依次执行for循环中的语句,如果使用var定义,for循环结束后 i 的值为5,所以依次执行setTimeout输出的是五个5

for (let i = 0; i < 5; ++i) { 
 setTimeout(() => console.log(i), 0) 
} 
// 会输出 0、1、2、3、4 

而在使用 let 声明迭代变量时,JavaScript 引擎在后台会为每个迭代循环声明一个新的迭代变量。 每个 setTimeout 引用的都是不同的变量实例,所以 console.log 输出的是我们期望的值,也就是循 环执行过程中每个迭代变量的值。

1.1.3 const的使用

声明

const 的行为与 let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且 尝试修改 const 声明的变量会导致运行时错误。

1.1.4 使用优先

因为在ES6中引入了块作用域的概念,所以优先使用let和const,在知道变量不需要更改的时候选择使用const,在知道未来需要修改时使用let

1.2 数据类型

1.2.1 基本数据类型

javascript中有7种数据类型 Undefined、Null、Boolean、Number、String、Symbol(ES6新增)、Object

1.2.2 typeof操作符
let message = "some string"; 
console.log(typeof message); // "string" 
console.log(typeof(message)); // "string" 
console.log(typeof 95); // "number" 
//第一个message是 字符串“message” ,第二个是变量message

在这个例子中,我们把一个变量(message)和一个数值字面量传给了 typeof 操作符。注意,因 为 typeof 是一个操作符而不是函数,所以不需要参数(但可以使用参数)

1.2.3 Undefined

Undefined 类型只有一个值,就是特殊值 undefined。当使用 var 或 let 声明了变量但没有初始 化时,就相当于给变量赋予了 undefined 值

Undefined 是一个假值。

1.2.4 null

null 类型同样只有一个值,即特殊值 null。逻辑上讲,null 值表示一个空对象指针,这也是给 typeof 传一个 null 会返回"object"的原因

null 是一个假值。

1.2.5 Boolean

要将一个其 他类型的值转换为布尔值,可以调用特定的 Boolean()转型函数

数据类型转换为true转换为false
Booleantruefalse
String非空字符串空字符串
Number非00、NaN
Object任意对象null
Undefined不存在转换为true的情况Undefined
1.2.6 Number
浮点值

因为存储浮点值使用的内存空间是存储整数值的两倍,所以 ECMAScript 总是想方设法把值转换为 整数。在小数点后面没有数字的情况下,数值就会变成整数。类似地,如果数值本身就是整数,只是小 数点后面跟着 0(如 1.0),那它也会被转换为整数,如下例所示

let floatNum1 = 1.; // 小数点后面没有数字,当成整数 1 处理
let floatNum2 = 10.0; // 小数点后面是零,当成整数 10 处理

计算浮点数时存在精度问题

计算一些浮点数时,javascript会 采用IE754转换成二进制,然后再进行计算,计算完成后再将结果转换成10进制,因此存在四舍五入的问题。

解决方案 先把小数转成整数.在计算, 最后把结果再转换成小数就ok了

function MathTool() {

	//获取小数长度
	var getDecimalsLength = function (num) {
		return num.toString().split(".")[1] ? num.toString().split(".")[1].length : 0
	}
	
	//获取最大长度
	
	var getMaxLength = function (num1, num2) {
	
		var num1Length = getDecimalsLength(num1);
		
		var num2Length = getDecimalsLength(num2);
		
		var p = Math.max(num1Length, num2Length);
		
		var times = Math.pow(10, p);
		
		return times
	
	}
	
	//加法
	
	this.add = function(num1, num2) {
	
		var times = getMaxLength(num1, num2);
		
		return (this.mul(num1 ,times) + this.mul(num2 ,times)) / times;
		
	}
	
	//减法
	
	this.sub = function(num1, num2) {
	
		var times = getMaxLength(num1, num2);
		
		return (this.mul(num1 ,times) - this.mul(num2 , times)) / times;
		
	}
	
	//乘法
	
	this.mul = function(num1, num2) {
	
		var times = getMaxLength(num1, num2);
		
		var intNum1 = num1.toString().replace(".", "")
		
		var intNum2 = num2.toString().replace(".", "")
		
		var countDecimals = getDecimalsLength(num1) + getDecimalsLength(num2)
		
		return intNum1 * intNum2 / Math.pow(10, countDecimals);
		
	}
	
	//除法
	
	this.div = function(num1, num2) {
	
		var times = getMaxLength(num1, num2);
		
		return (this.mul(num1 , times) / this.mul(num2 , times));
		
	}
	
}
	
	var MathTool = new MathTool();
	console.log(MathTool.add(0.1, 0.2))
	console.log(MathTool.sub(0.0012, 0.0002))
值的范围(Infinity)

ECMAScript 可以表示的最小 数值保存在 Number.MIN_VALUE 中,这个值在多数浏览器中是 5e324;可以表示的最大数值保存在 Number.MAX_VALUE 中,这个值在多数浏览器中是 1.797 693 134 862 315 7e+308。如果某个计算得到的 数值结果超出了 JavaScript 可以表示的范围,那么这个数值会被自动转换为一个特殊的 Infinity(无 穷)值。任何无法表示的负数以-Infinity(负无穷大)表示,任何无法表示的正数以 Infinity(正 无穷大)表示。

NaN

有一个特殊的数值叫 NaN,意思是“不是数值”(Not a Number),用于表示本来要返回数值的操作 失败了(而不是抛出错误)。比如,用 0 除任意数值在其他语言中通常都会导致错误,从而中止代码执 行。但在 ECMAScript 中,0、+0 或 -0 相除会返回 NaN

如果分子是非 0 值,分母是有符号 0 或无符号 0,则会返回 Infinity 或-Infinity

任何涉及 NaN 的操作始终返回 NaN(如 NaN/10),在连续多步计算 时这可能是个问题。其次,NaN 不等于包括 NaN 在内的任何值

(NaN == NaN)// false

isNaN() 该函数接收一个参数,可以是任意数据类型,然后判断 这个参数是否“不是数值”。把一个值传给 isNaN()后,该函数会尝试把它转换为数值。某些非数值的 值可以直接转换成数值,如字符串"10"或布尔值。任何不能转换为数值的值都会导致这个函数返回 true。

console.log(isNaN(NaN)); // true 
console.log(isNaN(10)); // false,10 是数值
console.log(isNaN("10")); // false,可以转换为数值 10 
console.log(isNaN("blue")); // true,不可以转换为数值
console.log(isNaN(true)); // false,可以转换为数值 1
数值转换

Number()、parseInt()和 parseFloat()

1.2.7 String

字符串可以使用双引号(")、 单引号(’)或反引号(`)标示,因此下面的代码都是合法的

几乎所有值都有的 toString()方法。这个方法唯 一的用途就是返回当前值的字符串等价物

注意模板字符串的 ` ` 调用,在模板中应用${ } 插入js语句

1.2.8 Symbol(ES6新增)
声明
//普通声明
const level1 = Symbol();
console.log(level1) //Symbol()
//在声明中定义
const level2 = Symbol("level");
console.log(level1) //Symbol("level")
//描述相同不代表两个对象相同
const level3 = Symbol("level")
console.log(level3 == level4)//false
使用Symbol() 添加对象属性
const level = Symbol("level")
const student = {
	name:'xiaoming',
	age:12,
	[level]:"A"
}
//for in 遍历对象不能获取Symbol
for(let pro in student){
    console.log(pro);//name,age
}
console.log(student[level]);//A
Symbol.iterator

如果对象有 Symbol.iterator这个属性,这个对象就可以被for…of遍历

1.2.9 Object

ECMAScript 中的对象其实就是一组数据和功能的集合。对象通过 new 操作符后跟对象类型的名称 来创建。开发者可以通过创建 Object 类型的实例来创建自己的对象,然后再给对象添加属性和方法

constructor:用于创建当前对象的函数。在前面的例子中,这个属性的值就是 Object() 函数。

 hasOwnProperty(propertyName):用于判断当前对象实例(不是原型)上是否存在给定的属 性。要检查的属性名必须是字符串(如 o.hasOwnProperty(“name”))或符号。

 isPrototypeOf(object):用于判断当前对象是否为另一个对象的原型。(第 8 章将详细介绍 原型。)

 propertyIsEnumerable(propertyName):用于判断给定的属性是否可以使用(本章稍后讨 论的)for-in 语句枚举。与 hasOwnProperty()一样,属性名必须是字符串。  toLocaleString():返回对象的字符串表示,该字符串反映对象所在的本地化执行环境。

 toString():返回对象的字符串表示。

 valueOf():返回对象对应的字符串、数值或布尔值表示。通常与 toString()的返回值相同。

1.2.10 操作符
递增递减

无论使用前缀递增还是前缀递减操作符,变量的值都会在语句被求值之前改变。(在计算机科学中, 这通常被称为具有副作用。)请看下面的例子

let age = 29; 
let anotherAge = --age + 2; 
console.log(age); // 28 
console.log(anotherAge); // 30 

后缀版递增和递减在语句被求值后才发生

let num1 = 2; 
let num2 = 20; 
let num3 = num1-- + num2; 
let num4 = num1 + num2; 
console.log(num3); // 22 
console.log(num4); // 21 
String和Number相加

Number数值会转换成String类型

let result1 = 5 + 5; // 两个数值
console.log(result1); // 10 
let result2 = 5 + "5"; // 一个数值和一个字符串
console.log(result2); // "55"
== 和 === 的区别

==会将数据类型进行转换

=== 不会将数值类型进行转换

let result1 = ("55" == 55); // true,转换后相等
let result2 = ("55" === 55); // false,不相等,因为数据类型不同
for…in…

for-in 语句是一种严格的迭代语句,用于枚举对象中的非符号键属性

语法如下: for (property in expression) statement

for-in用于遍历对象

for…of…

for-of 语句是一种严格的迭代语句,用于遍历可迭代对象的元素

语法如下: for (property of expression) statement

for-of用于遍历数组

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值