WY-javascript笔记

严格模式


曾益

  • 消除js语法的一些不合理、不严谨、不安全问题,减少怪异行为并保证代码运行安全
  • 提高编译器效率,增加运行速度

使用

  • 全局使用严格模式

      <script>
      "use strict";
      (function(){
          console.log("hello world!");
      })()
      </script>
    
  • 函数内使用严格模式

      <script>
      (function(){
          "use strict";
          console.log("hello world!");
      })()
      </script>
    
  • 标准与严格模式的区别

    • 隐式声明或定义变量
    • 对象重名的属性
    • 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 <u>create,keys....</u>

原型对象属性、方法

  • <u>coustructor, toString,valueOf,hasOwnProperty....</u>
原型对象

Object.create
基于原型对象创建新对象

语法
Object.create(proto[,propertisObject])

 var proto = {a:1,b:2};
 var obj = Object.create(proto);
__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
  • <b>对象 -> true <b>

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,<u>splice,forEach,find,concat,pop,push,reverse,shift,slice....</u>

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)
Point自定义对象

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 将字符串转化为数字

Paste_Image.png

encodeURIComponent 将URI参数中的中文、特殊字符等作为URI一部分进行编码

使用举例:URL中参数编码


encodedURIComponent举例

表达式


概念: 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

运算符优先级

Paste_Image.png

语句


  • 条件控制语句 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语句可能导致执行性能下降,应该尽可能的避免使用
with

变量作用域


  • 生命周期
  • 作用范围

静态作用域 在编译阶段就知道变量的引用

  • 又称为 词法作用域
  • 有程序定义的位置决定
Paste_Image.png
根据foo函数找到全局的X

动态作用域 由动态栈来决定

  • 程序运行时刻决定
x为20

JS变量作用域


  • js 使用静态作用域
  • js 没有块级作用域
  • ES5中使用词法环境管理静态作用域

词法环境

组成

  • 环境记录(形参,变量,函数等)
  • 对外部词法环境的引用(outer),最外层的词法环境是none

什么时候创建词法环境?

  • 一段代码开始执行前,先初始化词法环境。
    • 形参
    • 函数定义
    • 变量定义

词法环境-问题

  • 形参、函数定义、变量定义名称冲突
  • arguments
  • 函数表达式

JS 作用域-带名称的函数表达式

   (function A() {
         A = 1;
         alert(A);
    })();

首先看,这段代码,在全局的词法环境中,没有函数定义,没有变量定义,也没有形参。A是一个函数表达式,不是一个函数定义。所以不会被定义到全局的词法环境中。

此时,会把A单独定义一个词法环境。 里面的record是A函数,A函数内部是不能被修改的。所以,A=1是无效的。此时alert(A) 弹出的还是A函数。

Paste_Image.png

闭包

  • 闭包有函数和与其相关的引用环境的组合而成
  • 闭包允许函数访问其引用环境中的变量(又称自由变量)
  • 广义上来说,所有JS的函数都可以称为闭包,因为JS函数在创建事保存了当前的词法环境。

闭包的应用

  • 保存变量现场
  • 封装

保存变量现场 示例:

保存变量

封装示例:

封装

程序设计方法


  • 面向过程

    • 以过程为中心
    • 自顶向下——逐步细化
  • 面向对象

    • 对象作为程序的基本单元
    • 程序分解为数据和相关操作

JS面向对象

  • construtor
  • this
  • 原型继承
  • 原型链
  • 应用

Constructor 创建构造器的三种形式

  • function Employee(){...} //函数定义
  • var Emloayee = function(){...} //函数表达式
  • var Emloayee = new Function(); //new Function

this

Paste_Image.png

构造器中的this 表示 即将创建的新对象。
JS 中,函数的this指向函数的调用者。在该例子中,构造器中的函数里面的 this表示的是p1,函数的调用者

New Function中的this,指的是,全局对象(window)

new Function

eval中的this,指调用上下文中的this

eval中的this

第一个闭包中的 eval上下文是全局,所以,this指向全局对象global ,window

第二个eval中的this调用上下文是在bar函数中的,所以 eval 中的this 与 bar函数中的this一样,bar函数的this指的是其调用者也就是Foo对象。

总节

this.png

原型

原型链

  • 属性查找
  • 属性修改
  • 属性删除

原型链-属性查找

属性查找&修改
 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])

create

思考:如何在低版本浏览器实现Object.create功能?

URL

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


未完待续


推荐阅读更多精彩内容