JavaScript笔记 – 程序语法设计

一、基础语法设计

       JavaScript是可以与HTML标记语言混合、用于网页交互式的解释型脚本语言。由国际标准ECMAScript提供核心语言功能、文档对象模型(DOM)提供访问和操作网页内容的方法和接口、浏览器对象模型(BOM)提供与浏览器交互的方法和接口 三部分组成,基本所有的浏览器支持ECMAScript,但不同的浏览器对于DOM和BOM支持具有很多差别。

1、Script引用语句

     在HTML文档中可以在页面的任意位置(建议在<head>标签)定义多个<script>标记,<script>标记定义的方式有 定义js代码段 通过src属性引入js文件两种方式。浏览器从上到下、边解释边运行<script>标记,在引用<script>标记中可使用defer属性将其设置为延迟加载(当页面都加载完成后在使用window.onload加载)

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    //使用src引入js脚本文件,其中延迟加载defer=”defer” 只能用于这种方式
    <script type="text/javascript" src='./js/HelloWord.js' defer>
        //引用外部文件,内部代码将不会被执行
        window.alert("该语句不会被执行!");
    </script>
    //定义js代码段,通过不同的对象打印 HelloWord
    <script type = "text/javascript" >
        window.alert("浏览器对象打印Hello Word!");
        document.write('文档对象打印Hello Word');
        console.info('控制台打印Hello Word');
   </script>

2、流程控制语句

(1)选择控制结构

//单选择结构
if(逻辑判断条件) 语句块;

//双分支选择结构
if(逻辑判断条件)
        语句块1;
  else
        语句块2;
//条件表达式
(条件表达式1)?表达式2:表达式3 ;

//多分支选择结构
if(逻辑判断条件1)
      语句块1;
else  if(逻辑判断条件2)
      语句块2;
else
      语句块3;
//switch条件匹配语句
switch(表达式)
{
	case const1:  语句块1;
	case const2:  语句块2;
        .....
	default:  语句块n;
}

(2)循环控制结构

//for循环语句
for(初始化语句;循环判断语句;增量语句)
{
	语句块;
}
//while语句
while(循环判断语句){
	语句块;
}
//do while语句
do{
	语句块;
}while(循环判断语句);

//特别的: for循环可以不写循环条件表示true,但while循环中不谢循环条件会编译出错。
for(;;){
  语句块; //死循环
}

(3)跳转语句

//break语句跳出当前循环,执行下一条语句
var count = 0;
for(var a = 1; a <= 9; a++){
    if(a == 3) continue;
    count++;
}
alert(count);   //循环9次,计数结果为8

//continue语句结束当前某一次循环,执行下一个循环
var count = 0;
for(var a = 1; a <= 9; a++){
    if(a == 3) break;
    count++;
}
alert(count);//计数结果为2

//labe with语句

3、垃圾收集机制

     JavaScript是一门具有自动垃圾收集机制的编程语言,开发人员不必担心内存分配和收集的问题。若变量离开作用域且未被使用,则将被自动标记为可回收,可以在垃圾回收期间被删除。垃圾收集算法有标记方法和引用计数法,其中标记清除算法是目前最主流的垃圾收集算法。

function fun(){
    var a = 10;//被使用
    var b = 20;//被使用
}
fun();
//执行完后,a,b被标记为未被使用,等待垃圾收集机制回收

二、Function函数类型

1、函数定义方式

        定义函数的方式有function语句形式、函数直接量形式以及Function构造函数形式,Function具有动态性,每new一个就生成一个函数,多用于只用于调用一次的函数;function具有静态特性,多个相同的函数只会编译一次,用于多次调用。执行JavaScript代码时,会优先解析function,再按顺序从上至下执行语句或解析函数。这三张方式区别如下:

            image

(1)函数声明与调用

//方法一:使用function语句
//js 弱类型语言,可不声明就使用 如:参数列表
function 函数名(参数列表)
{
    语句块;
    return语句;//返回结果并终止止函数执行
}
var result = func1(1,2);//返回3 ,该方式调用可以写在声明前面
var type = typeof (func2);//显示  function  类型
var F = 函数名;  //函数赋值
函数名 = null;  //函数删除
alert (函数名) //返回函数的定义代码

//方法二:函数直接量形式
//函数是一种引用数据类型,可以直接赋予变量
var func2 = function(){
     语句块;
     return语句;
}

//方法三:使用构造函数的方式
var func3 = new Function("a","b","return a+b");

//方法四:作为对象定义
//在js中定义一个对象,等同于定义一个函数,只是对象名大写
function Call(value){
    var a=1,b=2;            //私有属性,外部无法访问
    var dc = function(){    //私有方法,外部无法访问
        alert("内部方法");
    }
    alert(a+b);             //初始化代码块
    this.value = value;     //public属性,使用this动态绑定
    this.ds = function(){   //public方法
        alert("Helloword");
    }
}
var obj  =new Call(6); //显示  3  ,类似于函数调用的方式
obj.ds();              //显示  Helloword
obj.value;   //返回  6  
obj.a;  //undefined,无法访问
obj.dc;                //error, obj.dc is not a function
//特别的:若将函数作为一个对象,也可以使用对象设置属性的方式设置属性
obj.other = 6;                     //public属性,使用this绑定
obj ['birthday'] = '2001-02-06';   //public属性,使用this绑定
obj.method = 函数;                 //public属性,使用this绑定

//嵌套函数定义
function online(){
    function inline(){
       alert("inline");
    }
    inline();//执行inline函数
}
online();

(2)函数的解析顺序

       js解析函数时,先解析function,无重载会覆盖,代码从上往下执行。特别的,使用function定义的函数,调用可以写在声明前面。

 //① 第一遍
  // 函数1被函数4覆盖,自上而下优先解析function
  // 函数4被函数2覆盖,Function顺序解析
  // 函数2被函数3覆盖,直接量顺序解析
  //② 第二遍
  // 函数4被函数3覆盖,function不会再次解析
  // 函数3被函数5覆盖,Function顺序解析
  // 函数5被函数6覆盖,直接量顺序解析
function f(){return 1;}               alert(f());//4       //函数1
var f = new Function("return 2;");    alert(f());//2       //函数2
var f =  function(){return 3;} ;      alert(f());//3       //函数3
function f(){return 4;}               alert(f());//3       //函数4
var f = new Function("return 5;");    alert(f());//5       //函数5
var f =  function(){return 6;} ;      alert(f());//6       //函数6

2、函数参数列表

     函数参数分为实参和形参,内部是通过一个arguments数组去接收函数的实际参数的,要注意:arguments只能在函数内部访问和使用。

(1)arguments对象

function func(a,b){
    //防止形参与实参个数不相等,导致运行错误
    if(func.length == arguments.length){
        return arguments[0]+arguments[1];
    }else{
        return "参数不正确";
    }
}

(2)callee函数

 function one(num){
    if(num <1) return 1;
    return num * one(num-1);
  }
  alert(one(5));//正确,显示120

  //问题描述
  var One = one;
  one = null;
  //  alert(One(5));//错误,因为f已经被置为null,不能进行递归运算

  //解决方案
  function two(num){
      if(num <1) return 1;
      //返回arguments对象所属函数的引用
      return num * arguments.callee(num-1);
  }
  var Two = two;
  two = null;
  alert(Two(5));//正确,显示120

3、函数作用域

    执行环境定义了变量或函数链=有权访问的其他数据,每一个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在设个对象中,该对象只能由js解析器访问。当代码个环境中执行时,会创建变量对象的一个作用域链(scope chain),用于保证在执行环境中,对有权访问的所有变量和函数可以进行有序访问。

    全局执行环境是最外围的一个执行环境,根据ECMScript实现所在的宿主环境不同,表示执行环境的对象也不同。每一个函数都有自己的执行环境,当执行某一函数时,函数的环境就会被推入一个环境栈中,而在环境执行完成之后,栈将其环境弹出,把控制权返回给之前的执行环境。

(1)函数静态作用域

//① 执行环境 window对象(最上层的环境)
var n = 1;
var k = 4;
//每一个函数都有一个执行环境(variable obj)
function func() {
    //② 一级作用域
    var k = 3;
    function func1(){ 
        //③ 三级作用域
        alert(n);//低级作用域可以访问上级作用域中的内容
        var k = 2;
        alert(k);//但若有冲突,则以当前作用域中的变量
    }
    var func2 = function(){
        //②二级作用域,不可访问3级作用域
        alert(k);
    };
    //① Function是一级作用域
    var func3 = new Function('alert(k);');
    func1();//1,2
    func2();//3,alert(k)与写在func()函数内一样
    func3();//4,Function是全局作用域
}
func();

(2)this动态绑定作用域

       this对象是在运行时基于函数执行环境绑定的,其永远指向调用者,在全局函数中,this对象指向window,而当函数被某个对象的方法调用时,this指向那个对象。

var k = 10;
function func(){
    var k = 20;
    this.k = 30;
}
func();

alert(func.k);  //undefined,外部无法访问局部变量
alert(k);       //30  , this指向的对象是Window

(3)块级作用域

        在C、Java等高级语言中,for、if语句具有块级作用域,但在JavaScript中,没有块级作用域的概念,只有函数作用域的概念。

function func(){
    for(var i = 1;i<=5;i++){}
    alert(i); //显示6

    (function(){ for(var n = 1;n<=5;n++){}})();
    alert(n); //n is not defined
}
func();

(4)call与apply函数扩展作用域

        每一个函数都具有call和apply这两个非继承来的方法,可以在特定的作用域中调用函数,扩展函数的作用域。实际上等于设置函数体内this对象的值。

//call 和 apply函数可以用于传递参数
function sum(x,y){
    return x+y;
}
function func(){
    //call和apply用于绑定不同的作用域
    var cal = sum.call(this,1,2.2);
    var apy = sum.apply(this,[1,2]);

    alert(cal);
    alert(apy);
}
func();

//扩展作用域
window.color = 'black';
var obj = {color:'red'};

function showColor(){
    alert(this.color);
}
showColor.call(window);//black
showColor.call(obj);//red
//=====================================
//特别的:call方法简单模拟
 function mycall(a,b){
     return a+b;
 }
 //自定义对象
function Obj(x,y){
     this.x = x;
     this.y = y;
     return x* y;
}
var obj = new Obj(6,7);
obj.call = mycall;
Obj(6,7);//返回42
obj.call(obj.x,obj.y);//返回13
delete obj.call;

4、函数回调与闭包

       函数也是一种引用数据类型,若函数作为实际参数,则可以与调用函数共用一个作用域(回调函数);若函数作为返回值,则在函数内访问另一个函数的作用域(闭包是运行期中的动态环境)。

(1)回调函数

function recall(fn){
    var a=1,b=2;
    fn(a,b);
}
recall(function(a,b){
    alert(a+b);
});

(2)Closure闭包

var name = "外部";
var obj = {
    name : "内部",
    getOut:function(){
        return function (x) {
            this.name = this.name+x;
            return this.name;//动态绑定
        }
    },
    getIn:function(){
        var o = this;//保存了obj对象
        return function (x) {
            o.name =  o.name + x;
            return o.name ;//参数调用
        }
    }
}
//函数obj.getOut()中属性是window.name,属于  【动态绑定】
alert(obj.getOut()(4));  //显示  外部4;
alert(obj.getOut()(4));  //显示  外部44;

//在函数中访问了obj.getIn()函数作用域的变量obj.name,属于 【闭包】
alert(obj.getIn()(5));   //显示   内部"5;
alert(obj.getIn()(5));   //显示   内部"55;

三、面向对象设计


四、接口开发与设计

posted @ 2018-02-05 22:20  苏贺  阅读(176)  评论(0编辑  收藏  举报