严格模式
曾益
- 消除js语法的一些不合理、不严谨、不安全问题,减少怪异行为并保证代码运行安全
- 提高编译器效率,增加运行速度
使用
-
全局使用严格模式
-
函数内使用严格模式
-
标准与严格模式的区别
- 隐式声明或定义变量
- 对象重名的属性
- arguments.callee
- with 语句
- 其他。。。。
类型系统
标准类型
前五种为原始类型, object为引用类型
- undefined
- null
- boolean
- string
- number
- object
保存区别
复制区别
类型说明
undefined 出现场景
- 已声明未赋值的变量
- 获取对象不存在的属性
- 无返回值的函数的执行结果
- 函数的参数没有传入
- void(express)
undefined类型转换
Boolean: Boolean(undefined) === false
值 | Boolean | Number | String |
---|---|---|---|
undefined | false | NaN | "undefined" |
null出现的场景
-
null表示对象不存在
document.getElementById('notExistElement')
null类型转换
值 | Boolean | Number | String |
---|---|---|---|
null | false | 0 | "null" |
Number类型转换
值 | Boolean | String |
---|---|---|
0 | false | "0" |
1 | true | "1" |
Infinity | true | "Infinity" |
NaN | false | "NaN" |
类型识别
- typeof 识别标准类型(null除外),不能识别具体的对象类型(Function除外 )
- Object.prototype.toString 可以识别标准类型以及内置(build-in)对象类型,不能识别自定义类型
- constructor 可以识别标准类型(undefined/null除外-没有构造器);识别内置对象;识别自定义类型
- instanceof 判别内置对象类型;不能判别原始对象类型;判别自定义对象类型
Object.prototype.toString:可以识别标准类型以及内置(build-in)对象类型,不能识别自定义类型
function type(obj){
return Object.prototype.toString.call(obj).slice(8,-1).toLowerCase();
}
type(1) //number
type('abc') //string
type(true) //boolean
type(undefined) //undefined
type(null) // null
type({}) //object
type([]) // array
type(new Date) //date
type(/\d/) //regexp
type(function(){}) //function
function Point(x,y){
this.x = x;
this.y = y;
}
type(new Point(1,2)); //object
constructor例子.可以识别标准类型(undefined/null除外-没有构造器);识别内置对象;识别自定义类型
//判断原始类型
"jerry".constructor === String // true
(1).constructor === Number //true
true.constructor === Boolean //true
({}).constructor === Object //true
//判断内置对象
[].constructor === Array //true
//判断自定义对象
function Person(name){
this.name = name;
}
new Person('jerry').constructor === Person //true
内置对象
构造对象
- Object
- Boolean
- String
- Number
- Function
- Array
- RegExp
- Date
- Error
其他对象
- Math
- JSON
- 全局对象
对象Object
构造器说明
- object 是一组属性和方法的集合
- String/Number/Boolean/Array/Date/Error构造器都是Object子类对象,继承Object原型对象属性和方法。
实例化对象方法
var obj = new Object({age:12,name:'lili'})
var obj = {age:12,name:'lili'};
属性方法
- prototype create,keys....
原型对象属性、方法
- coustructor, toString,valueOf,hasOwnProperty....
Object.create
基于原型对象创建新对象
语法
Object.create(proto[,propertisObject])
例
var proto = {a:1,b:2};
var obj = Object.create(proto);
__proto__
称之为原型链,有如下特点:
-
__proto__
为对象内部的隐藏属性 -
__proto__
为实例化该对象的构造器的 prototype 对象的引用,因此可以直接方法 prototype 的所有属性和方法 - 除了 Object 每个对象都有一个
__proto__
属性且逐级增长形成一个链,原型链顶端是一个 Object 对象。 - 在调用属性或方法时,引擎会查找自身的属性如果没有则会继续沿着原型链逐级向上查找,直到找到该方法并调用。
-
__proto__
跟浏览器引擎实现相关,不同的引擎中名字和实现不尽相同(chrome、firefox中名称是__proto__
,并且可以被访问到,IE中无法访问)。基于代码兼容性、可读性等方面的考虑,不建议开发者显式访问__proto__
属性或通过__proto__
更改原型链上的属性和方法,可以通过更改构造器prototype 对象来更改对象的__proto__
属性。
Object.prototype.toString
获取方法调用者标准类型
obj.tostring()
Object.prototype.hasOwnproperty
判断一个属性是否是对象自身属性
obj.hasOwnProperty(prop)
var proto = {a:1,b:2};
var obj = Object.create(proto);
obj.c = 1
obj.hasOwnProperty('c'); // true
obj.hasOwnProperty('a'); // false - a是对象原型连上的属性
其他类型像布尔类型转换
- 数字 0,NaN -> false
- 字符串 “” -> false
- undefined -> false
- null -> false
- 对象 -> true
String.prototype.replace 查找字符串替换成目标字符
stringObj.replace(regexp/substr,replacement)
var str = "1 plus 1 equal 3"
str = str.replace("1","2") //str = "2 plus 1 equal 3"
str2.replace(/\d+/g, '$ & dollor')
//"2 dollor plus 1 dollor equal 3 dollor"
注:以上$ & 之间没有空格
**String.prototype.split **
stringObj.split(separator,howmany)
var str = "1 plus 2 equal 3"
str.split(" ") //["1","pluls","2","equal","3"]
str.split(" ",3) //["1","pluls","2"]
str.split(/\d+/); //[""," plus "," equal ",""]
**Number.prototype.toFixed **
把Number四舍五入为制定小数位数的数字
numberObj.toFixed(num)
Array
- 构造器对象属性、方法 - prototype,isArray [用法:Array.isArray(obj)]
- 原型对象属性、方法
-constructor,splice,forEach,find,concat,pop,push,reverse,shift,slice....
Array.prototype.splice
从数组中删除或添加元素,返回被删除的元素列表(会更改原有的数组)
arrayObj.splice(start,deleteCount[,item1[,items....]])
Array.prototype.forEach
遍历数组元素并调用回调函数
arrayObj.forEach(callback[,thisArg])
function callback(value,index,arrayObj){.....}
function logArray(value,index,array){
console.log(value)
console.log(value === array[index])
}
//Note ellision,there is no member at 2, so it isn't visited
[2,5, ,9].forEach(logArray)
结果:2 true 5 true 9 true
Function
用于定义函数或者新对象构造器
实例化函数方法
- 对象实例化
- 函数关键字语句
- 函数表达式
原型对象属性、方法 - constructor,apply,call,bind
实例对象属性、方法 - length,prototype,arguments,caller
自定义对象构造器
//自定义构造器
function Point(x,y){
this.x = x
this.y = y
}
//自定义属性
Point.prototype.move = function(x,y){
this.x += x
this.y += y
}
//实例化
var p = new Point(0,1)
Function.prototype.apply
通过参数指定函数调用者和函数参数并执行该函数
functionObj.apply(thisArg,[argsArray])
例1
Object.prototype.toString.apply("123") //[object String]
例2
//自定义构造器
function Point(x,y){
this.x = x
this.y = y
}
//自定义属性
Point.prototype.move = function(x,y){
this.x += x
this.y += y
}
//实例化(原点)
var p = new Point(0,0)
p.move(2,2) //移动到2,2点
var circle = {x:1,y:1,r:1} //以原点为x=1,y=1,半径为1的圆
//移动圆到3,2
p.move.apply(circle,[2,1]); //后面的参数为move所需参数.[x:3,y:2,r:1]
Function.prototype.bind
通过参数指定函数调用者和函数参数并返回该函数引用
functionObj.bind(thisArg[,arg1[,arg2[,....]]])
function Point(x,y){
this.x = x
this.y = y
}
Point.prototype.move = function(x,y){
this.x += x
this.y += y
}
var p = new Point(0,0)
p.move(2,2)
var circle = {x:1,y:1,r:1}
//实现过一段时间再移动圆,bind
var circleMove = p.move.bind(circle,2,1) // 返回函数引用
setTimeout(circleMove,1000)
子类构造器
function Circle(x,y,r){
Point.apply(this,[x,y])
this.radius = r
}
/**
Circle.prototype = new Point()
delete Circle.prototype.x
delete Circle.prototype.y
**/
简化如下:
Circle.prototype = Object.create(Point.prototype)
Circle.prototype.constructor = Circle
Circle.prototype.area = function(){
return Math.PI*this.radius*this*radius
}
var c = new Circle(1,2,3)
c.move(2,2)
c.area()
函数调用
- ()
- apply, call
函数参数
- 形参个数不一定等于实参个数
- 值传递
- 通过参数类型检查实现函数重载
函数重载
define(function(){
var add = function(x, y) {
return x + y;
};
return {
add: add
};
})
define(['lib'], function(){
var add = function(x, y) {
return x + y;
};
return {
add: add
};
})
define('math', ['lib'], function(){
var add = function(x, y) {
return x + y;
};
return {
add: add
};
})
// define 的实现代码
/**
* The function that handles definitions of modules. Differs from
* require() in that a string for the module should be the first argument,
* and the function to execute after dependencies are loaded should
* return a value to define the module corresponding to the first argument's
* name.
*/
define = function (name, deps, callback) {
var node, context;
//Allow for anonymous modules
if (typeof name !== 'string') {
//Adjust args appropriately
callback = deps;
deps = name;
name = null;
}
//This module may not have dependencies
if (!isArray(deps)) {
callback = deps;
deps = null;
}
// 省略以下代码
// ...
};
正则表达式
构造器说明:用于定义正则表达式,一个 RegExp 对象包含一个正则表达式和关联的标志
-
定义方法
- /pattern/flags
- new RegExp(pattern[, flags]);
属性及方法
prototype-
原型对象属性及其方法
- constructor
- test
- exec
...
** RegExp.prototype.test **
功能:使用正则表达式对字符串进行测试,并返回测试结果
regexObj.text(str)
var reg = /^abc/i;reg.test('Abc123');
truereg.test('1Abc1234'); // false
Date
构造器说明:用于定义日期对象
-
定义方法
var date0 = new Date(); var date1 = new Date(2014, 3, 1, 7, 1, 1, 100);
-
属性及方法
- prototype
- parse
- now
- ...
-
原型对象属性及其方法
- constructor
- Date
- getDate
- getHours
- setDate
- setHours
- ...
其他内置对象,Math,JSON,全局对象
Math
rondom, floor,ceil,round,abs,max,cos
Json
parse,stringify
全局对象
属性: NaN, Infinity, undefined
方法:parseInt, parseFloat, isNaN,isFinite, eval ...
处理URL方法: encodeURIComponent, decodeURIComponent, encodeURI, decodeURI
构造器属性:Boolean,String,Number,Object,Function,Array,Date,Error.....
对象属性:
Math,JSON
var url = "http://www.baidu.com/reg.html?name="+ encodeURIComponent(name)
NaN
- 表示错误或无意义的运算结果
- NaN参与运算返回仍然是NaN
- NaN不等以任何值,包括NaN本身
- 可以用isNaN()判断运算结果是否为NaN
eval
可以计算某个字符串,并执行其中的javascript代码。eval(string)
parseInt 将字符串转化为数字
encodeURIComponent 将URI参数中的中文、特殊字符等作为URI一部分进行编码
使用举例:URL中参数编码
表达式
概念: js短语,解释器可以执行它并生成一个值
关系运算符
=== 类型与值都相等
==判断两边对象或值是否相等
以下都为true
- "99" == 99
- new String("99") == 99
- true == 1
- false == "0"
- '\n\n\n' == false
非数值类型做==比较时,先转换为数值类型
==例外规则
- null == undefined //true
- null或undefined参与进行==运算时不进行隐式类型转换
- 0 == null //false
- null == false //false
- "undefined" == undefined //false
逻辑运算 !
- !表示 运行结果转换为boolean值后取反
- !!表示去表达式的运行结果的boolean值
逻辑运算 &&
- X && Y 并且。如果X 如果为false,怎终止Y的运算,返回false。如果X为true,则继续运行Y,返回Y的boolean值。
逻辑运算 ||
var a = 0
var b = 0 || ++a
结果:a,b 为1,1
运算符优先级
语句
- 条件控制语句 if else; swith case ( case中的判断是=== )
- 循环控制语句 for/in; for; while ... do while...
- 异常处理语句 try/catch/finally throw
- with语句 with(){....}
for/in
遍历对象的属性
for(key in objS ){...}
with
- 用于缩短指定情形下必须写的代码量
- 暂时改变变了的作用域链,将with语句中的对象添加到作用域链的头部
- 缺点: with语句可能导致执行性能下降,
应该尽可能的避免使用
变量作用域
- 生命周期
- 作用范围
静态作用域 在编译阶段就知道变量的引用
- 又称为 词法作用域
- 有程序定义的位置决定
动态作用域 由动态栈来决定
- 程序运行时刻决定
JS变量作用域
- js 使用静态作用域
- js 没有块级作用域
- ES5中使用词法环境管理静态作用域
词法环境
组成
- 环境记录(形参,变量,函数等)
- 对外部词法环境的引用(outer),最外层的词法环境是none
什么时候创建词法环境?
- 一段代码开始执行前,先初始化词法环境。
- 形参
- 函数定义
- 变量定义
词法环境-问题
- 形参、函数定义、变量定义名称冲突
- arguments
- 函数表达式
JS 作用域-带名称的函数表达式
(function A() {
A = 1;
alert(A);
})();
首先看,这段代码,在全局的词法环境中,没有函数定义,没有变量定义,也没有形参。A是一个函数表达式,不是一个函数定义。所以不会被定义到全局的词法环境中。
此时,会把A单独定义一个词法环境。 里面的record是A函数,A函数内部是不能被修改的。所以,A=1是无效的。此时alert(A) 弹出的还是A函数。
闭包
- 闭包有函数和与其相关的引用环境的组合而成
- 闭包允许函数访问其引用环境中的变量(又称自由变量)
- 广义上来说,所有JS的函数都可以称为闭包,因为JS函数在创建事保存了当前的词法环境。
闭包的应用
- 保存变量现场
- 封装
保存变量现场 示例:
封装示例:
程序设计方法
-
面向过程
- 以过程为中心
- 自顶向下——逐步细化
-
面向对象
- 对象作为程序的基本单元
- 程序分解为数据和相关操作
JS面向对象
- construtor
- this
- 原型继承
- 原型链
- 应用
Constructor 创建构造器的三种形式
- function Employee(){...} //函数定义
- var Emloayee = function(){...} //函数表达式
- var Emloayee = new Function(); //new Function
this
构造器中的this
表示 即将创建的新对象。
JS 中,函数的this指向函数的调用者。在该例子中,构造器中的函数里面的 this
表示的是p1,函数的调用者
New Function中的this,指的是,全局对象(window)
eval中的this,指调用上下文中的this
第一个闭包中的 eval上下文是全局,所以,this指向全局对象global ,window
第二个eval中的this调用上下文是在bar函数中的,所以 eval 中的this 与 bar函数中的this一样,bar函数的this指的是其调用者也就是Foo对象。
总节
原型
原型链
- 属性查找
- 属性修改
- 属性删除
原型链-属性查找
tom.name = 'Tom Green' ; //首先查找自身属性,找到name 然后修改
tom.job = 'assistant'; //自身找不到job属性,然后找原型链有job属性,然后给自身添加job属性,属性值为assistant,并不修改原型的job属性。
teacher.prototype.job = 'assistant' //修改原型的job属性。那么访问:bill.job 得到的是 assistant.
原型链-属性删除
delete tom.job //只是删除tom上的job属性,如果在访问,则去原型上找job属性,并不会删除原型上的属性。
思考:如果判断一个属性来自于对象本身?
//hasOwnProperty 判断是否来自对象本身。
tom.hasOwnProperty('job')
ES5中的原型继承
Object.create(proto[,propertiesObject])
思考:如何在低版本浏览器实现Object.create功能?
JS面向对象编程
全局变量
- var test = 'some'
- window.test = 'some'
- (function(){ var a;
test = 'some' // 前面没写var 被定义到全局
} )()
封装问题——信息隐藏
function A(){
this.a = null;
this.b = null;
this.step1 = function(){
//TODO
}
this.step2 = function(){
//TODO
}
this.api = function(){
//TODO
}
}
封装形式
类继承
ClassA是父类,ClassB是子类
原型继承
右侧的clone 是兼容低版本浏览器不支持ES5的create
未完待续