html5语言实现进栈出栈代码,JavaScript语法基础1--2018-9-12

javascript是什么? 有什么用?

(1).javascript是最流行的,而且是唯一的写"前端脚本"的编程语言;

(2).前端主要是指:html,css,javascript,以及相关的开发框架,函数库等,共同特征就是指可以直接在浏览器中运行;

(2).脚本语言的一个基本特征是,可以使用标签,以元素的形式直接嵌入到html文档中,例如,<?php ?>;

(3).javascript功能极其强大,强大到令人发指,前后端几乎通吃,但它最主要的功能仍是实现用户与页面的交互操作;

---------------------------------------------------------------------------------------------------

2. 如果将js代码写到html中?

(1). 使用标签:

(2). 可以添加一个属性 type="text/javascript"表示脚本的类型,但考虑到js是前端唯一并且是默认脚本,所以推荐省略掉

(3). js代码可以写到标签中,类似css中页内样式,仅限当前文档使用

(4). 如果想将js代码应用到更多的html文档中,可以在起始标签

类似css中的外部样式表,实现脚本共享,这也是js最常用的方式,写到独立文件中,不仅可页页共享,还能缓存,提升加载速度.

(5).

(6). 浏览器是可以禁用js的,但这种情况极期罕见,毕竟大多应用是基于js,所以大家在学习时可以忽略用户是否禁用js脚本.

---------------------------------------------------------------------------------------------------

3. js运行结果的三种输出方式

(1). alert()弹窗 let site = 'php中文网'; alert(site);

(2). write()方法: document.write(site);

(3). console.log()控制台: console.log(site);

4.. 基本语法:

(1).字面量[值]: 'php中文网';  99; js中,字面量非常强大,将功能发挥到了极致,一定要格外重视

(2).变量[名称/标识符]: 临时存放数据的地方,就是数据的占位符而已,例如:site = 'php中文网'; price = 99;

(3).操作符:主要有算术运算(+,-,*,/,=)与逻辑运算(==,!==,===,<,>...)二类,重点是操作符对操作数的类型转换;

例如: 15 + 20 // 35;    '15' + 20 // 1520,字符串拼接;

(4).注释: 与php类似, 单行//,多行 /* ... */;

(5).语句: 用分号';'结束,分号并非必须有,可以省略,近些年越多越多的开发者都开始省略分号,但在学习阶段,为了避免入坑,推荐加上;

5. js脚本的基本组成部分: 变量和函数,下面咱们先聊聊变量:

(1). 变量使用ESC6标准的: let声明, 函数使用 function 声明;

(2). 传统的使用var声明,不支持块作用域,并且允许重复声明,let完美的解决以上问题,推荐使用;

(3). 什么是块作用域? if(){...}, for(){...},之前js只支持一种函数作用域,这和php是一样的;

(4). php到目前为止,仍不直接支持块作用域,可以使用其它技术来模拟,使用闭包等;

(5). var 和 let 声明变量的区别:

1. let支持块作用域,var不支持

if (true) {

var n = 100;     // var声明,块作用域外部可以拿到

let n = 100;     //let声明,块作用域外部拿不到

}

console.log(n);

2. let不允许重复定义,var允许

let name = 'peter';

let name = 'zhu';  // 报错

var salary = 5800;

var salary = 6800; // 不报错

(6). let 变量声明时未初始化,默认值为undefined,undefined是一种特殊的类型,一会再说

(7). let 变量提升时,会报引用错误,而var会输出undefined,所以推荐必须先声明再初始化,或者声明初始化二合一;

(8). 以后尽可能使用let来声明和使用变量,大家把var 忘了吧

6. 变量的数据类型

(1). js数据类型分为二大类: 原始类型与引用类型; js不允许自定义数据类型,因为js是动态的,可以模拟出任何类型,不需要自定义

(2). 原始类型有五种: String字符串,Number数值(不区分整数和浮点数),Boolean布尔,Undefined未定义,Null类型

(3). 引用类型:[Object对象, Array数组]重点掌握,Function函数, Date日期,RegExp正则, 包装对象...

(4). 类型检测: typeof ,只能检测出: 原始类型与函数,其它都返回Object,

typeof 'abc'    // "string"

typeof 100      // "number"

typeof true     // "boolean"

typeof null     // "object" ,正确应该返回:"null",这是历史遗留问题,暂时无解

typeof undefined    // "undefined"

typeof [1,2,3]      // "object"

typeof {x:1,y:2}    // "object"

typeof function f1(){}  // "function"

对于引用类型,应该使用 instanceof

let o = {x:1,y:2}

o instanceof Object     // true

instanceof 检测数组类型是会有问题:

[1,2,3] instanceof Array    // true

[1,2,3] instanceof Object   // true,因为数组也是对象,返回true也应该是对的

正确方法应该是使用Array的isArray()方法

Array.isArray([1,2,3])      // true

Array.isArray({x:1,y:3})    // false

Array是数组对象的构造函数,一会再说

--------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------

7. 函数:

在学习之前,咱们先学点其它的玩意:

现在跟着我大写朗读三遍: "js中,一切皆对象"

只是牢记这句话,后面的课程,你才会搞明白,否则从根上就把你干蒙逼了~~~

(1).函数是js中的一等公民,不仅是代码执行的基本单元,也是创建其它成员的基本类型;

(2).函数按功能分为二大类: 普通函数,构造函数;

(3).按创建方式分为: 函数声明,函数表达式,匿名函数,自执行函数;

(4).函数声明自动提前:因为函数如此重要,所以函数声明会自动提升到代码最前面,不论在脚本的什么地方声明,都可以直接使用;

(5).函数调用必须使用函数名加上一对圆括号;

(6).函数中可以使用return 返回结果,如果没有return 语句,函数执行完毕,会返回 undefined ;

function f1() {}

f1()    // undefined

function f2(){return 'php.cn'}

f2()    // "php.cn"

(7).每次执行函数,都会自动创建一个函数作用域,与外部临时隔离,函数外部成员在函数作用域内可见,反之则不行;

let m = 100;        // 该变量声明在函数外部,全局范围内可见

function f3() {

return m +50;   //函数外声明的变量全局可见

}

f3()    // 150

function f4(){

let n = 20; //函数内声明的变量,外部不可见

}

m +n    // n 未定义,出错

(8).函数表达式

表达式通常会返回一个确定的值,所以可以直接将表达式用到需要值的地方

let f5 = function (){ return 200; }

150 + f5()      // 350, f5()可直接看到一个值,内容就是调用f5()函数的结果

(9).匿名函数:主要用做函数的参数

[1,2,3,4].filter(function(item,index,array){return item>2;})

(10).自执行函数:声明完直接运行,不需要调用

(function(a,b){return a+b;})(20,40)     // 60

(11)函数的参数问题:

1. js根本不在乎函数有没有参数,以及参数有多少,是什么类型;

2. 因为在内部是使用一个数组来接收这些参数,并使用对象 arguments 来访问这个数组

3. 因此函数中的参数只是一个实际参数的占位符而已,仅起提示作用,所以也叫: "命名参数"

4. 命名参数仅提供了访问便利,并非必要;

5. arguments对象, 可以像使用数组一个使用它,例如:arguments[1],但它并不是Array对象的实例;

6. arguments.length 属性中保存着参数的数量

7. js中没有函数签名,不存在函数重载(相同的签名,不同的实现)

7. 但是js可以用动态参数来模拟重载: 案例:根据参数不同,执行不同的操作

//声明

function add() {

var num = arguments.length

switch (num) {

case 0:

return '至少要有一个参数'

break

case 1:

return arguments[0]

break

case 2:

return arguments [0]+arguments[1]

break

case 3:

return arguments[0]+arguments[1]+arguments[2]

break

default:

return '参数过多'

}

}

//调用

add() // '至少要有一个参数'

add(100) // 100

add(100,200)  // 300

add(100,200,300) // 600

add(100,200,300,400) // '参数过多'

---------------------------------------------------------------------------------------------------

8. 数组 Array

1. Array 是仅次于 Object 外使用频率最高的引用类型;

2. Array 是有序列表,每一个数组元素可以保存任何类型的数据;

3. Array 的长度是可以动态调整的,自动增长;

4. 与Object类似,创建Array数组也有二种式: 实例化构造函数Array, 字面量

(1). 构造函数Array

var arr = new Array()  //实例化Array(),创建空数组

var arr = new Array(3) // 创建的新数组有三个预置元素,默认值都是undefined

var arr = new Array(3,5,'a') //一个或一个以上非数值元素,就是创建实际的内容而非长度

var arr = Array([1,2,3],'php','html') //可省略new,可传入数组等多种类型给构造函数

(2). 字面量

var arr = ['html','css','javascript']; //字面量

var arr = []; // 空数组

无论使用哪一种方式,都会有二个默认的属性:

1. length: 数组元素的数量

2. __proto__:

5. length 属性的特殊用途:

(1). Array.length : 是可读可写的,可人为设置,实现数组元素的移除与添加;

(2). Array.length : 它的值始终比元素最大索引大1,可以用作永远指向下一个元素的索引;

(3). 添加元素

var arr = []  // 空数组

arr[arr.length] = 100  // arr.length = 0,等价于arr[0] = 100

arr[arr.length] = 200

arr[arr.length] = 300

(4). 删除元素

var arr = ['html','css','javascript','jquery','vue.js']

arr.length   // 当前数组长度: 5 ,即有5个元素

arr[arr.length-1]   // 获取最后一个元素的值: 'vue.js'

arr.length -= 1    // 将数组长度减1, 即当前数组长度更新为: 4

arr[arr.length-1]  // 获取最后一个元素的值: 'jquery'

6. 创建新数组

(1):基于当前数组中的所有项,创建一个新数组: concat()

var arr = [1,2,3]

arr.concat(4,5)     //

arr.concat([6,7,8]) // 接受数组参数,这个数组会拆开,将每一个元素并入原数组中:[1, 2, 3, 6, 7, 8]

(2).基于数组的开始与结束的位置来创建: slice() 单词本意: 切开

slice(起始索引[,结束索引]),如省略结束索引,默认为后面全部数据

var arr = [10,20,30,40,50]

arr.slice(2)        // 从索引2开始,获取后面全部内容: [30, 40, 50]

arr.slice(1,4)      // 从索引1开始,到索引4结束(不含索引4): [20, 30, 40]

(3).向数组中间插入数据: splice(), 功能主要是: [删除,插入,替换]

参数说明: splice(start,length,value...)

1). 删除

arr.splice(起始,删除数)

var arr = [10,20,30,40,50]

arr.splice(0,2)     // 从头部0,开始删除2个,返回删除的元素: [10, 20]

2). 插入

arr.splice(起始,0,要插入项)

arr.splice(1,0,88,99) //第二个参数0,表示插入,插入的数据是第三个参数

//本例是从第二个元素起,插入二个新元素:88,99:

arr     // 查看当前数组: [30, 88, 99, 40, 50]

3). 替换

arr.splice(起始,删除数,要插入项)//第二个参数1,表示替换,

arr.splice(2,1,'dog','cat')     // 返回删除项: 99

arr     // 查看数组: [30, 88, "dog", "cat", 40, 50]

7. 栈方法

(1).数组可以模拟栈操作

(2).栈是一种LIFO(Last_In_First_Out)'后进先出'的数据结构,插入与删除只能是栈顶(一端)进行

(3).push()入栈, pop()出栈

(4).举例

var arr = []     // 创建空数组

arr.push(10,20)  // 将数组看成栈,入栈二个元素,10先入,20后入,返回数组长度:2

arr              // 查看当前数组: (2) [10, 20]

arr.length       // 查看当前数组长度: 2

arr.push([1,2])  // 入栈一个数组元素,返回长度: 3

arr              // 查看数组: (3) [10, 20, (2) [1, 2]

arr.pop()        // 出栈(栈顶元素出栈):  (2) [1, 2]

arr.pop()        // 继续出栈: 20

8. 队列方法

(1).与栈方法相对的是队方法:FIFO(First_In_First_Out):先进先进

(2).因为栈方法:push()可以从数组未端添加元素,所以只需要一个方法可以从前端获取元素即可

(3).从数组前端获取元素的方法就是:shift(),并自动将数组长度减1;

(4):push() + shift() 实现队操作:尾进头出

var arr = [10,20,30]

arr.push(40)     // push()尾部入队: 40

arr.length       // 此时数组长度是: 4

arr              // 查看队列: (4) [10, 20, 30, 40]

arr.shift()      // shift()从前端(头部出队),返回出队元素: 10,长度自动减1

arr.length           // 当前数组长度是: 3

(5):unshift(),可以在数组前添加任意数组的元素,并更新数组长度,与栈方法pop()配合实现队操作

(6):unshift() + pop() 实现队操作:头进尾出

var arr = [10,20,30]

arr.unshift(3,5)     // unshift()入队操作: 头部添加二个新元素,并自动更新长度

arr.length           // 新长度: 5

arr                  // [3,5,10,20,30]

arr.pop()            // pop()出队操作: 返回出队元素: 30,并更新长度

arr.length           // 新长度: 4

9. 重排序方法

(1).反转: reverse()

var arr = [1,2,3,4,5]

arr.reverse()       // 数组元素翻转:(5) [5, 4, 3, 2, 1]

(2).sort()更加的灵活

var arr = [10,4,22,8,2]

arr.sort()      // [10, 2, 22, 4, 8]:显然错误,因为sort()默认将元素视为字符串,'10'显然是小'2'

//解决方案: sort()可接受一个回调参数,在回调函数中进行比较运算完成正确排序

function compare(val1,val2){

if (val1 < val2) {

return -1

} else if (val1 > val2) {

return 1

} else {

return 0

}

}

***对于数值型元素的比较,这个回调函数可以进行简化:

function compare(val1,val2) {

return val - val2  //升序

}

arr.sort(compare)       // 输出正确结果:[2, 4, 8, 10, 22]

//如果改为降序排列,只需要改变回调中的返回值即可

function compare(val1, val2) {

return val2-val1   //降序: 用第二个参数减去第一个参数即可

}

arr.sort(compare)   // 降序: [22, 10, 8, 4, 2]

10. 位置方法

(1). indexOf(要查找的项 [,起始位置]): 从头部开始,查找失败返回: -1

(2). lastIndexOf(要查找的项 [,起始位置]): 从尾部开始,查找失败返回: -1

(3). 实例:在数组中查找指定元素并返回索引:

var arr = [1,2,3,4,5,4,3,2,1]

arr.indexOf(4)         // 查找4,返回4在数组中的索引位置: 3

arr.indexOf(4,4)       // 传入第二参数,指定从索引4开始查找,返回索引位置: 5

arr.lastIndexOf(4)     // 从尾部查找4,返回4第一次出的索引位置: 5

arr.lastIndexOf(4,4)   //从尾部查找4,从索引4开始,跳过了5,所以输出索引位置: 3

11. 迭代方法

(1). 5个方法都可以接受2个参数:每一顶上运行的回调函数(必选),运行该函数的作用域[可选](影响this的值)

(2). 这几个方法不会影响到原数组的值

(3). 五个方法介绍:

(1). every():如果每一项运算都返回true,则返回true;

(2). some(): 任一项运算返回true,则返回true;

(3). filter(): 返回true项组成的新数组;

(4). forEach(): 每一项执行给定函数,无返回值;

(5). map(): 返回每次执行结果组成的新数组

(4). 举例:

(1). every()

var arr = [1,2,3,4,5,6]

// 要求每一项都必须大于2,才可以返回true,显示第1,2个元素不符合要求

arr.every(function(item,index,array){ return item > 2 })

(2). some()

// 只要数组元素中有一个元素值大于2,就满足条件并返回true

arr.some(function(item,index,array){ return item > 2 })

(3). fileter()

// 返回数组中元素值大于2的元素,组成的新数组

arr.filter(function(item,index,array){ return item > 2 })

(4). forEach():注意无返回值,不要使用return ,常用来遍历数组

//输出全部的元素值

arr.forEach(function(item,index,array){ console.log(item) })

//输出元素的索引

arr.forEach(function(item,index,array){ console.log(index) })

// 输出当前正在遍历的数组元素:注意会把当前数组输出6遍

arr.forEach(function(item,index,array){ console.log(array) })

12. 归并方法

(1). 本质是数组元素之间的二二计算,并把结果带到下一次的运算中;

(2). reduce(): 从第一项开始迭代,直到计算出一个最终值;

(3). reduceRight(): 从最后一项开始迭代,向前遍历直到第一项;

(4). 都可以接受二个参数: 1迭代的函数,2是可选的归并初始值

(5). 迭代函数有四个参数: prev前一个,cur当前,index索引,array数组

var arr = [1,2,3,4,5]

// 计算:1+2+3+4+5的值

// 计算过程:

// 1 + 2 = 3

// 3 + 3 = 6

// 6 + 4 = 10

// 10 + 5 = 15

arr.reduce(function(prev,cur,index,array){return prev+cur})     // 结果: 15

//给reduce(callback,init)传入第二参数,计算的初始值: 10

arr.reduce(function(prev,cur,index,array){return prev+cur},10)  // 结果: 10 + 15 = 25

// reduceRight()功能与reduce()完全一致,只是计算方向从右边开始

arr.reduceRight(function(prev,cur,index,array){return prev+cur})    // 15

arr.reduceRight(function(prev,cur,index,array){return prev+cur},10) // 25

---------------------------------------------------------------------------------------------------

9. Object 类型

1.创建Object实例:

(1). 构造函数

var obj = new Object()

obj.name = 'Peter'

obj.age = 29

(2). 字面量

var obj = {

name: 'Peter',

age: 29

}

2. 表达式上下文: 花括号出现在赋值操作右边,就是一个表达式上下文,左花括号就是表达式的开始;

3. 语句上下文: 花括号出现在语句上下文中,例如 if/while...,则是语句块的开始;

4. 用字面量创建实例,最后一个属性后不要添加','号;

5. 属性名可以用字符串: var obj = {'name': 'zhu', 'sex': 'male'}

6. 可以创建一个只包含默认属性和方法的实例: var obj = {}  // obj只有默认属性和方法,等价于new Object()

7. 案例,根据参数是否有指定属性,输出对应的内容

function displayInfo(args) {

var output = ''

if (typeof args.name == 'string') {

output += 'Name: ' + args.name + '\n'

}

if (typeof args.age == 'number') {

output += 'Age: ' + args.age + '\n'

}

console.log(output)

}

displayInfo({name: '朱老师', age: 30})  // Name: '朱老师' Age: 30

displayInfo({name: '朱老师'})  //  Name: '朱老师'

displayInfo({age: 30})  //  Age: 30

displayInfo({'age': 30})  //  Age: 30

displayInfo({})   // 空

可以,无论输入什么,都可以得到正确的结果;

8. 通常情况下,必选参数使用命名参数比较好,当有多个可选参数时使用对象字面量时行封装会更灵活;

9. 刚才都是使用的点'.'语法来访问实例中的属性,支持属性名是标识符或字符串,其实也支持方括号;

10.使用方括号语法与数组类似,但是实例的属性/方法名必须放到引号中: obj['name']

var obj = {name:'peter', age: 30}

console.log(obj['name'])

console.log(obj['age'])

11.方括号语法还支持变量属性名:

var a = 'name'

var obj = {name:'zhu'}

obj.a // undefined

obj[a] // 'zhu'

*******************************************************************************************

对象的扩展知识:

一、对象的生成:

(1).对象字面量

1. 使用字面量生成对象的三种场景:

(1): 单例模式(singleton);

(2): 多值数据(函数的参数与返回值)

(3): 替代构造函数来生成对象

2. 场景一:单例模式

(1).所谓单例:将类的实例对象数量限定为一个;

(2).类是对象的模板,可以多次实例化,创建多个实例对象;

(3).如果只需要一个实例对象,但么就没必要去创建类了;

(4).所以使用字面量直接创建一个单例对象是最方便的啦.

var obj = {name:'peter', name:30}

3. 场景二: 多值数据的使用场景[类似于关联数组]

(1). 给函数传递多个参数

[传统方式:]

function getData(x, y, z) {

return (x+y+z)

}

getData(1,2,3)  // result: 6

[对象字面量做为函数调用的实参]

function getData(data) {

return (data.x+data.y+data.z)

}

getData({x:1, y:2, z:3})  // result: 6

[对象字面量做为默认参数]

//如果调用时没有传入实参

function getData(data) {

//函数内修改参数值并不是一个好习惯

data = data || {x:1, y:2, z:3}

return (data.x+data.y+data.z)

}

getData()  // result: 6

[对象字面量做为函数返回值]

function func() {

return {x:4, y:5, z:6}

}

func()  // {x:4, y:5, z:6}

[扩展知识,返回数组,并实现将数组中元素转为独立变量的技巧]

function func() {

return [4, 5, 6]

}

[x,y,z]=func()  // 将数组中的元素转为独立的变量

x   // x = 4

y   // y = 5

z   // z =6

4. 场景三: 代替构造函数

(1). 构造函数是用来创建对象的,所以只需要将对象字面量做为函数返回值即可;

(2). 从语法上看,与返回多值数据基本相同,区别在于执行方式;

(3). 实例:

function createObj() {

//直接将对象字面量做为返回值

return {

x: 10,

y: 20,

z: 30,

sum: function () {

return this.x + this.y + this.z

}

}

}

var obj = createObj()

obj.sum()   // 结果: 60

createObj().sum()   //使用链式调用进行简化

(2). 构造函数与new表达式

1. 构造函数是一种必须要通过new表达式调用的特殊函数;

2. 构造函数的用途是用来创建对象(类的实例化);

3. 因为类可以被实例化为对象,所以类中必须要有该实例对象的代言人;

4. 这个特殊的类中对象的代言人,就是伪变量: this

5. 构造函数基本用法:

(1).声明: function MyClass(x, y) {

this.x = x

this.y = y

}

(2).调用: var obj = new MyClass(10,20)

obj.x  // 10

obj.y  // 20

6. 总结:

(1).构造函数本身与普通函数声明形式是相同的;

(2).构造函数是通过"new"表达式来调用;

(3).new 表达式的值: 新对象的引用

(4).new 表过式是通过构造函数内的this引用了新生成的对象

(一).new 表达式的操作

new 操作的完整流程

1. new 表达式 首先是新生成一个"操作对象"(可视为一个通用对象,是对象就具备访问属性和调用方法的能力);

2. 用这个"操作对象"调用指定的函数(即构造函数);

3. 构造函数内部有一个内部指针:this,指向了这个由"new"表达式新生成的操作对象;

4. 在构造函数中,可以使用this为当前操作对象添加属性或方法;

5. 构造函数执行完成,将会返回该操作对象的引用:this, 做为new 表达式的 "值"

6. 即: new 操作 的最终返回值,其实就是构造函数中的: this

(二).构造函数的调用

1. 其实任何函数都可以通过 new 来调用,所以任何函数都可以充当构造函数的角色;

2. 但只有一个函数内部使用了this,他才是一个构造函数,可以生成一个新对象;

3. 构造函数结尾会隐式一条: return this 语句,返回当前对象的引用;

4. js中的构造函数类似于其它语言中的类,但却又比他们难以理解,毕竟new一个函数来生成一个对象比较特殊;

5. 而其它语言,都是 new 一个类,而js中没有类的概念,所以构造函数,实际上就起到了"类"的作用;

6. 因为构造函数起到了"类"的作用,所以按照惯例,充当构造函数的函数名,首字母应该大写,以示不同;

---------------------------------------------------------------------------------------

八、属性的访问

1. 属性访问:

(1).点语法,只能使用标识符: obj.name;

(2).中括号[],必须使用字符串,可用用字符串字面量,也可以用字符串变量

var obj = {name:'peter', age:20}

obj.name    // 'peter'

obj['age']  // 20

var p = 'name'

obj[p]  // 'peter'

({x:40,y:50}).x // 40,说明访问属性的是对象的引用

({x:40,y:50}).y // 50

实际开发过程中,可能遇不到直接对字面量对象进行运算,但是在链式调用很方便

2. 属性设置与访问的规则相同:

var o = {}

o.name = 'jack'

o['age'] = 30

3. 属性值的更新

1.将属性表达式写在"="号左侧

obj.name = 'zhu'    // 如果属性存在则是更新,如果不存在就是创建新属性

delete obj.name     // 删除对象obj上的属性name

4.点运算符与中括号运算符的区别

1. 能使用点运算符"."的场景,一定能使用中括号运算符"[]",反之则不一定;

2. 访问属性首选点运算符,当"."会产生歧义时,则使用中括号来规避,例如属性名是一个非法标识符

3. 以下三种情况必须使用中括号:

(1).使用了非法标识符: 属性名多个单词之间有空格,连接线-或特殊字符$#%.等

(2).使用了变量属性名: var p = 'name'; obj[p];

(3).使用了表达式的属性名:

var obj = {x:10, y:20}

var m = 5       // 定义变量 m ,初始值为5

obj[ (m<10)? 'x' : 'y']     // m当前值小于10,返回true,此时输出obj.x的属性值: 10

var m =13       // 更新m, 使其大于10

obj[ (m<10)? 'x' : 'y']     // m当前值大于10,返回true,此时输出obj.y的属性值: 20

5.属性的枚举: for (var key in obj) { console.log(obj.key) }

*******************************************************************************************

变量的扩展知识:

一、变量的声明

1. 变量可以用来表示某个值,或某个变量;

2. 变量使用前应该先声明:var m ;

3. 声明未赋值(初始化); 默认为: undefined;

4. 对同一个变量可以重复声明;

推荐语法:

var a = a || 10;    //已声明则用原值,未声明用默认值

var a ;     // 已声明未初始化,默认值:undefined

var a = 40;  // 40  // 初始化40

--------------------------------------------------------------

二、变量与引用

1. 变量分为: 基本类型, 引用类型;

2. 变量赋值: 值传递, 引用传递;

3. 基本类型变量也叫值型变量,复制采用值传递,二者是完全独立的;

4. 引用类型变量与叫引用变量,类似于C语言指针,二者共同指向同一对象;

基本类型:

var a = 123;

var b = a;  // a 值 传递 给 b

b++ // b 自增1

b   // b=124

a   // a无变化

引用类型

var a = {x: 10, y: 20};

b = a;  // 将对象a复制到b中,对象是引用赋值,a和b指向同一个对象

b.x     // 10

b.x = 30;  // 将b.x 属性重新设置为30

a.x         // a.x 属性同步被更新为30

a = {a: 88, b: 99}  // 改变a变量的值,使其引用另一个对象

a   // 查看对象a, 它的值已发生变化: {a: 88, b: 99}

b   // 查看b,发现仍是原来的对象内容:{x:30,y:20}

此时原对象的引用保存在变量b中,这与证明了对象变量的确是引用类型

函数的参数

1. 函数传参是使用值传递方式进行;

2. 经典案例:交换二个变量的值

var a = 100;

var b = 200;

//swap()实现交换

function swap(a,b) {

return [b, a];

}

[a,b] = swap(a,b);  //执行交换操作

a   // a等于200

b   // b等于100

字符串与引用

1. 字符串是基本类型,基本类型的值都是不可改变的;

2. 字符串内部仍是按引用方式来实现的,但表现为值传递;

引用总结

1. 赋值应该是从右向左看: var a = {x:1,y:2};

2. 应该是先有一个对象{x:1,y:2},然后再声明一个标识符a来引用它;

3. 所以无论是否存在变量a, 对象{}都是客观存在的;

4. 因此,即使变量a指向了其它对象: var a = {m:5,n:6},而对象{x:1,y:2}仍存在

5. 当对象{x:1,y:2}没有任何引用指向时,系统将启动回收机制销毁该对象

--------------------------------------------------------------

二、变量与属性

(1)全局变量与全局对象之间的关系:

1. 在js中一切皆对象,所有变量就是属性,属性就是变量;

2. 变量或属性名的用途: 获取值[右值] 或者 被赋值[左值];

3. 根据作用域: '全局变量' 和 '局部变量(函数参数)';

4. 全局变量: 函数之外声明的变量;

5. 局部变量: 函数内部声明的变量;

6. 全局变量(包括全局函数名)是"全局对象"的属性;

7. 全局对象: 程序一旦开始运行,就会被自动创建;

8. 证明: 全局变量 === 全局对象的属性

var x = 'foo'   // 声明全局变量并初始化'foo'

x   // 以全局变量方式访问 'foo'

this    // 查看当前全局对象, 浏览器中的js是: window

this.x  // 以对象属性方式访问全局变量x

9. 如果将全局对象,赋值给一个全局变量,做为该对象的引用的话

var global = this   // 声明全局变量global, 用全局对象this初始化

10.这时,全局变量,他具有双重身份: 1. 全局变量; 2. 全局对象this的引用

这就是传说中的: 自己引用自己

'global' in this    // 返回: true, 说明全局变量global的确是this(全局对象)的属性

global  // 返回 window对象, 说明 global 本身的确是全局对象

11. 这种自引用关系,在js中非常常用,例如在客 户端javascript中,就提供了一个引用了全局对象的

全局变量:window, 这个window 就类似于我们上面创建的全局变量global的作用.

12. 全局对象和全局变量的生命周期: 从脚本开始运行直到脚本结束(关闭当前页面).

(2)局部变量与对象之间的关系

1. 函数内部声明的变量,以及函数的参数都是局部变量;

2. 与全局变量一样,局部变量也会被隐式的声明为某个对象的属性;

3. 这个隐式的对象就是: call;

4. 局部变量的生命周期: 通常从函数调用直到函数执行结束返回调用者;

5. 可以通过一种称作:"闭包"的技术,打破这个约束,使局部变量离开函数仍可以使用.

--------------------------------------------------------------

四、变量的查找

1. 无论是左值,还是右值操作,都会触发对变量名称的查询操作;

2. 在最外层代码(函数之外)的变量查找,实际上查找的是全局对象的属性(全局变量与全局函数);

3. 在函数内部的变量名查找,因为在函数内部可以使用全局变量,所以首先是查找call对象的属性,

如果没找到,再到全局对象属性上查找,是由内到外的顺序进行: call对象 --> global对象

--------------------------------------------------------------

五、对变量或属性是否存在的检测

(1):对变量是否存在进行检测(以全局变量为例):

1. 常用语法: var a = a || 10; // a有值由用原值,否则使用默认值:10

2. 变量复制: var a; var b = a || 10;  // 原理同上

3. 变量复制: var a; var b = a != undefined ? a : 10; // 判断a是否有值

4. 利用js没有块级作用域特征,使用typeof 进行再精确的判断

var a

if (typeof a != undefined) {

var b = a

} else {

var b = 10

}

b++     //因为没有块级作用域,所以这里可以使用变量 b

5.以上都必须先对a进行声明,其实可以用 'in' 判断是否是某对象的属性来判断:in this

if ( 'm' in this) {var n = m} else {var n = 20} //然后就可以使用变量n了

(2):对属性是否存在进行检测:

1. 属性存在时,与变量一样,返回它的值;

2. 当属性不存在时,与变量的返回完全不同;

3. 访问不存在的变量会返回错误,而属性只会返回undefined

age     // 返回错误

this.age    // undefined

---------------------------------------------------------------------------------------

js中的流程控制:

与其它编程语言一样,也有分支与循环二大类,语法与php基本一致

1. 判断

(1).单分支: if () {}

(2).双分支: if(){} else {}

(3).多分支: if(){} else if () {} else {}

(4).switch: switch(n) {

case 1:

break;

...

default:

break;

}

2. 循环

(1). for(let i=0; i

(2). while(){...}   /  do {...} while()

(3). for in:   for (let var in obj)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值