接触Web开发也已经有一段时间了,对javascript的认识也比以前有了更加深入的认识了,所以觉得应该整理一下。

一、JavaScript不支持函数(方法)的重载,用一个例子证明如下: 
function add(number) 

    alert('hello'); 
}

function add(number1, number2) 

    alert('world'); 

此时调用add(1),会弹出'world',而不是'hello',由此现象说明写在文档后面的方法会覆盖掉前面的方法,所以有一个我认为暂时是正确的原则,就是如果方法名相同,则以后面对方法为主。

二、JavaScript中函数(方法)就是一个对象,这里就不解释了,看一个例子比较直观 
function add(number) 

    alert('hello'); 

是等价于下面这种写法的 
var add = new Function("number","alert('hello')"); 
以此类推 
function add(number1, number2) 

    alert('world'); 

等价于 
var add = new Function("number1","number2","alert('world')"); 
这里一和二都是一样的,只是写法不同,底层是一样的,所以可以把JavaScript的不支持重载的现象按照面向对象的概念来理解:首先add对象指向第一个Function对象,而后引用的对象改变了,指向了第二个新的Function对象了。示意图如下

所以可以得出一个这样的结论:JavaScript中的每个函数function都是new出来的Function对象。 
   
三、如果在调用某个JavaScript函数的时候,没有给函数中的参数传值,则参数为undefined,例子如下: 
function add(number) 

    alert(number); 
    alert(number + 30); 

当在触发处调用add()的时候,显然没有传入参数值,此时先弹出undefined(未定义), 
然后弹出NaN(不是一个数Not A Number)

四、arguments是每个函数的内置对象,应用这个内置对象可以模拟面向对象的重载功能,例如 
function sum() 

    if(1 == arguments.length) 
    { 
        alert(arguments[0]); 
    } 
    else if(2 == arguments.length) 
    { 
        alert(arguments[0] + arguments[1]); 
    } 
    else if(3 == arguments.length) 
    { 
        alert(arguments[0] + arguments[1] + arguments[2]); 
    } 

调用如下: 
sum(1);    =>    1 
sum(1, 2);    =>    3 
sum(1, 2, 3);    =>    6

五、由上面的例子又可以得到,JavaScript的函数就是Function的对象,函数都有一个length属性,表示函数接收参数的个数。证明如下: 
function add() {.....} 
function minus(num) {....} 
function multiply(num1, num2) {.....} 
调用如下: 
alert(add.length)    =>    0 
alert(minus.length)    =>    1 
alert(multiply.length)    =>    2

六、JavaScript中有五种原始值,可以理解为原生数据类型(这里仅仅是值JavaScript的,不同于3GL语言),它们分别是:Undifined,Null,Boolean,Number,String 
(1)Undefined数据类型的值只有一个:undefined,这里要注意一点就是,对于JavaScript中的变量,如果只声明,而没有赋值,则该变量的值为undefined。 
例如:var s;    alert(s);   此时弹出的是undefined

(2)Null数据类型的值只有一个:null

(3)Boolean数据类型的值有两个:true和false

(4)任何整数或者浮点数都是Number数据类型中的值,另外typeof(..)函数会返回参数的类型名称,例如: 
var s;   alert(typeof(s));     弹出undefined 
var a = 1;    alert(typeof(a));    弹出number 
var b = 'hello';    alert(typeof(b));    弹出string     双引号表示原始类型在栈里 
而var c = new String("hello");    alert(typeof(c));    弹出object,是在堆中的对象了

(5)一个函数如果不返回值,则返回'undefined',typeof(..)返回的值是字符串类型的,证明如下: 
function aa() {..//里面没有return出值..}         alert(aa()); 会弹出undefined

function bb() {....;   return;  }      alert(bb);会弹出bb函数体{}中的所有源代码内容

(6)使用没有声明,并且没有赋值的变量会报错,例如, 
var s;    alert(s2);  因为s2没有声明也没有赋值,所以会报错 
alert(typeof(s));  弹出undefined 
alert(typeof(s2));  尽管s2没有声明也没有赋值,但会弹出undefined

由此可以归纳出,typeof(..)的返回值有五个:undefined,boolean,number,string,object;

(7)null与undefined的关系:undefined实际上是从null派生而来的,证明如下, 
alert(undefined == null);    会弹出true

(8)在函数体内加不加var的区别:如果在函数体的内部,变量不加var,则默认该变量为全局变量,证明如下: 
function test() 

    var s = 'hello'; 

test(); 
alert(typeof(s));此时会返回undefined 
然而 
function test() 

    s = 'hello'; 

test(); 
alert(typeof(s));会弹出string 
alert(s);会弹出hello 
由此可知,对于函数定义中的变量来说,加var表示局部变量,不加var表示全局变量

(9)强制类型转换有三种:Boolean(value),Number(value),String(value) [这里可以看作函数] 
例如, 
var s = Boolean(null);    alert(s); 会弹出false 
var s = Boolean("");     alert(s);会弹出false 
var s = Boolean("a");   alert(s);会弹出true 
new Boolean(),new String("..."),new Number("...")都是object类型的

(10)在JavaScript中,Object是所有类的父类,类似于高级语言java 
var s = new Object(); 
alert(s);    弹出[object Object] 
alert(typeof(s)); 弹出object 
alert(s.propertyIsEnumerable("prototype"));弹出false,这里是判断s中的属性是否可以枚举出来

遍历window对象中的所有属性 
for(var temp in window) 

    alert(temp); 
}

delete操作和JavaScript中的晚绑定: 
var o = new Object(); 
o.name = "scott"; 
alert(o.name);   //会弹出scott 
delete(o.name); //删除晚绑定的name属性 
alert(o.name); //会弹出undefined

七、JavaScript的面向对象的特性: 
(1)JavaScript是基于ECMAScript的,构造对象时可以直接用名字,例如 
var object = new Object;       <=>        var object = new Object(); 
var s = new String;            <=>         var s = new String(); 
var date = new Date;         <=>        var date = new Date(); 
尽管如此,还是建议加上括号,增加可读性!!!!

(2)JavaScript中的数组,长度可以动态的增加,类似于java中的ArrayList,例如 
var array = new Array();        <=>      var array = [ ]; 
array.push(1); 
array.push(2); 
array.push(3); 
alert(array.length); //弹出3 
这里也可以用var array = [1,2,3];    alert(array.length); //弹出3

(3)数组对象有一个方法sort(),可以对数组进行升序排序,例如 
var array = [3,2,1]; 
array.sort(); 
alert(array); //弹出[1,2,3] 
咋一看,很爽,但是 
var array = [1,3,21]; 
array.sort(); 
alert(array); //弹出[1,21,3] 
原因就在于:sort()方法对数组进行排序的时候,首先将数组中的每一个元素都转化为字符串,即调用每个元素的toString()方法,然后用字符串的ASCII码进行比较! 所以'21' < '3'很正常! 
另外,sort()可以接受一个排序的函数作为参数,根据参数排序,类似于java中的compare()方法 
例如, 
function compare(num1, num2) 

    var temp1 = parseInt(num1); 
    var temp2 = parseInt(num2); 
    return temp1 - temp2; 

var array = [3,1,21]; 
array.sort(compare); 
alert(array);  //弹出[1,3,21] 
这里还可以用匿名函数的方法,类似于java中的匿名类 
array.sort(function(num1, num2) { 
    var temp1 = parseInt(num1); 
    var temp2 = parseInt(num2); 
    return temp1 - temp2; 
});

(4)对象的属性方式:[1]早绑定 [2]玩绑定
所谓早绑定,就是在对象生成之前绑定好的属性,例如,
var object = new Object();
object.name = "scott";
alert(object.name);

所谓晚绑定,就是对生成好的对象增加或减少它的属性,例如,
object.hello = function() { alert('welcome'); }
object.hello();  //此时会调用object的hello方法,弹出welcome
delete object.hello();  //删除方法
object.sayName = function() { alert(this.name); }  //这里this指的是object对象,类似于java一样
object.sayName();  //此时会弹出scott
object.sayName = function(name) {   //绑定一个传参数的方法
    this.name = name;
    alert(this.name);
}
object.sayHello('tiger');   //此时弹出tiger

=================================================================

一、用工厂方式定义对象(类),这里是参照java的设计模式的工厂模式写的,例子如下

function createObject()
{
    var object = new Object();  //这里请加上var,因为是方法体内部的局部变量
    object.username = "scott";
    object.password = "tiger";

object.get = function()
    {
        alert("username: " + this.username + "/npassword: " + password);
    }
    return object;
}
调用如下,
var o = createObject();
o.get();  //此时会弹出username: scott
          //         password: tiger
该方法的好处是凡是学要对象了,不需要自己new一个出来,直接可以通过createObject生成对象,具体的细节都被封装起来了~

上面的工厂方式固然有优点,但是生成的对象属性都被默认写死成scott和tiger了,所以可以改良成如下带参数的工厂方法,例子如下,
function createObject(username, password)
{
    var object = new Object();
    object.username = username;
    object.password = password;

object.get = function()
    {
        alert("username: " + this.username + "/npassword: " + password);
    }
    return object;
}
调用如下,
var o = createObject("scott","tiger");
o.get();
该方法的好处比起一楼的方式,就是更灵活的控制了要生成的对象。

然而对于以上两种工厂方式,方法get()定义在createObject()函数的内部,从性能上考虑,没创建一个对象,就要生成一个get的function对象,但是在高级语言java中所有的对象都共同的用同一个方法,需要注意到是在JavaScript中get方法不是如此,工厂每次生成对象的时候,都会为get再生成一次相同的对象,比较消耗内存,因此,可以将get方法的定义放在createObject之外。例如,

function get()
{
    alert("username: " + this.username + "/npassword: " + this.password);
}

function createObject()
{
    var object = new Object();
    object.username = "scott";
    object.password = "tiger";
    object.get = get;
    return object;
}
调用方法一样的,有点就是优化了性能,功能还是一样~

二、构造函数的方式
function Person()
{
    this.username = "scott";
    this.password = "tiger";
    this.get = function()
    {
        alert("username: " + this.username + "/npassword: " + this.password);
    }
}
用这种方法定义比较直观,与Java中生成对象很类似了,调用如下,
var person = new Person();
person.get();

注解:当调用new Person()的时候,执行流程跳到了函数中去了,在执行第一行代码之前,会生成一个对象,而this则会指向该对象,虽然没有return该对象,但是此构造函数隐式地将对象return出去了;

另外,传递参数也是类似的,内部函数的定义也可以改良从而降低对内存的消耗,将它拿到构造函数外面单独定义,所以可以改写成如下,
function get()
{
    alert("username: " + this.username + "/npassword: " + this.password);
}

function Person(username, password)
{
    this.username = username;
    this.password = password;
    this.get = get;
}

以上这种方式还是不够直观,有另一种解决方案如下,

原型方式创建类:prototype 
function Person(){ } 
Person.prototype.username = "scott"; 
Person.prototype.password = "tiger"; 
Person.prototype.get = function() 
{ alert("username: " + this.username + "/npassword: " + this.password); } 
调用方法: 
var p = new Person(); 
p.get();

但是这里使用prototype方法生成对象,不能创建的时候初始化值,必须等对象创建出来以后,对属性修改。 
var person1 = new Person(); 
var person2 = new Person(); 
person1.username = 'hello'; 
person1.get();   //hello tiger 
person2.get();   //scott tiger

JavaScript中的字符串也是不可变的,与java机制中一样,属于final类型的,字符串的拼接一会生成新对象

如果Person.prototype.username = new Array(); //如下面一楼贴出的图片person1和person2会共享scott
    person1.username.push("scott");
    person1.get(); //scott
    person2.get(); //scott

混合的构造函数与原型方式,属性采用构造函数的方式定义,方法采用原型方式定义(这里比较推荐这种方式)
可以避免上面的共享属性的弊端,例如,
function Person(username,password)
{
    this.username = username;  //这里如果this.username = new Array(); 则新对象不会共享username
    this.password = password;
}
Person.prototype.get = function()
{
    alert("username: " + this.username + "/npassword: " + this.password);
}
调用方法:
var p = new Person("scott","tiger");
p.get();

另外还有一种方式:动态的原型方式
function Person()
{
    this.username = "scott";
    this.password = "tiger";
    if(typeof Person.flag == "undefined")  //或者Person.flag == undefined
    {
        Person.prototype.get = function()
        {
            alert("username: " + this.username + "/npassword: " + this.password);
        }
        Person.flag = true;
    }
}

下面来看看用JavaScript模拟java的继承特性
(1)继承的第一种方式:对象冒充
function Parent(username)
{
    this.username = username;
    this.hello = function()
    { alert("username: " + this.username); }
}

function Child(username,password)
{
    this.method = Parent;
    this.method(username);
    delete this.method;
    this.password = password;
    this.world = function()
    { alert("password: " + this.password); }
}

根据上图,和带下划线的代码段,method属性作为桥梁引用Parent对象,调用Parent的构造函数后,删除了该属性!!
注意如果吧带下划线的代码段替换为Parent(username);是不行的,因为这样的话Parent中的hello()方法不能继承下来~

调用上面的继承
var parent = new Parent('father');
var child = new Child('son','scott');

parent.hello(); //father
child.hello();  //son
child.world();  //scott

由此可见继承机制确实实现了!!!!

(2)继承的第二种方式:call()方法
这里先介绍call()方法:每个function,即Function对象都有call()这个方法,call(param1,param2,...),
param1表示调用call()方法的函数内部的this,param2,...对应调用call()方法的函数中的参数列表,例如,

function test(str)
{
    alert(this.name + " " + str);
}
var obj = new Object();
obj.name = 'scott';
test.call(obj,'tiger'); //这里将obj对象赋给test中的this,弹出scott tiger

了解了call()的功能以后,我们来用call()实现继承机制,例子如下:

function Parent(username)
{
    this.username = username;
    this.hello = function()
    {
        alert(this.username);
    }
}

function Child(username, password)
{
    Parent.call(this,username);
    this.password = password;
    this.world = function()
    { alert(this.password); }
}

调用方法类似,这里就省略了。。。

(3)继承的第三种方式:apply()方式
这里对比一下apply()和call()
call(parm1,parm2,...,parmN)  多个参数

apply(parm1,new Array())  <=> apply(parm1,[parm2,...,parmN])  两个参数

归纳一下,apply方法的第一个参数和call一样,第二个参数是call后面参数组成的一个数组

下面用apply()来实现继承的机制,如下:
function Parent(username)
{
    this.username = username;
    this.hello = function()
    { alert(this.username); }
}

function Child(username,password)
{
    Parent.apply(this,new Array(username));  //等价于Parent.apply(this,[username]);
    this.password = password;
    this.world = function()
    { alert(this.password); }
}

(4)继承的第四种方式:原型链方式
function Parent() { }
Parent.prototype.hello = "hello";
Parent.prototype.sayHello = function()
{ alert(this.hello); }

function Child() { }
Child.prototype = new Parent();
Child.prototype = "world";
child.prototype.sayWorld = function()
{
    alert(this.world);
}

调用一下:
var child = new Child();
child.sayHello();  //hello
child.sayWorld();  //world

(5)继承的第五种方式:混合方式(最佳实践,推荐使用)

function Parent(hello)
{
    this.hello = hello;
}

Parent.prototype.sayHello = function()
{ alert(this.hello); }

function Child(hello,world)
{
    Parent.call(this,hello);
    this.world = world;
}

Child.prototype = new Parent();
Child.prototype.sayWorld = function()
{ alert(this.world); }

调用一下:
var child = new Child('hello','world');
child.sayHello();  //hello
child.sayWorld();  //world

最后举个例子来应用JavaScript的继承机制的应用

function Shape(edge) //一个抽象的形状
{
    this.edge = edge;
}

Shape.prototype.getArea = function() //获取形状的面积,类似于接口中的方法,这里先返回-1
{ return -1; }

Shape.prototype.getEdge = function() //返回形状的边有多少条
{ return this.edge; }

下面定义子类,三角形
function Triangle(bottom,height) //三角形,出入参数为底边和高
{
    Shape.call(this,3);
    this.bottom = bottom;
    this.height = height;
}
Triangle.prototype = new Shape();
Triangle.prototype.getArea = function() //返回三角形的面积,覆盖父类的方法
{ return 0.5 * this.bottom * this.height; }

调用三角形的对象和方法:
var triangle = new Triangle(10,4);
alert(triangle.getEdge()); //3
alert(triangle.getArea()); //20

下面再定义一个四边形
function Rectangle(bottom, height)
{
    Shape.call(this,4);
    this.bottom = bottom;
    this.height = height;
}
Rectangle.prototype = new Shape();
Rectangle.prototype.getArea = function()
{ return this.bottom * this.height; }

调用四边形的对象和方法
var rectangle = new Rectangle(10,20);
alert(rectangle.getEdge());  //4
alert(rectangle.getArea());  //200

JavaScript语言知识收藏的更多相关文章

  1. Javascript语言精粹之正则表达式知识整理

    Javascript语言精粹之正则表达式知识整理 1.正则表达式思维导图 2.正则表达式常用示例 2.1 移除所有标签,只留下innerText var html = "<p>& ...

  2. javascript语言精粹mindmap

    javascript语言精粹mindmap 最近刚刚读完<javascript语言精粹>,感觉其中的内容确实给用js作开发语言的童鞋们提了个醒——js里面坑很多啊 不过,我也并不完全认同书 ...

  3. AST抽象语法树——最基础的javascript重点知识,99%的人根本不了解

    AST抽象语法树——最基础的javascript重点知识,99%的人根本不了解 javascriptvue-clicommonjswebpackast  阅读约 27 分钟 抽象语法树(AST),是一 ...

  4. 第一章:Javascript语言核心

    本节是javascript语言的一个快速预览,也是本书的第一部分快速预览. 读此书之前,感谢淘宝技术团队对此javascript核心的翻译,感谢弗拉纳根写出此书.感谢你们无私的分享,仅以此笔记献给你们 ...

  5. 试读《JavaScript语言精髓与编程实践》

    有幸看到iteye的活动,有幸读到<JavaScript语言精髓与编程实践_第2版>的试读版本,希望更有幸能完整的读到此书. 说来读这本书的冲动,来得很诡异,写一篇读后感,赢一本书,其实奖 ...

  6. 【转】R语言知识体系概览

    摘要:R语言的知识体系并非语法这么简单,如果都不了R的全貌,何谈学好R语言呢.本文将展示介绍R语言的知识体系结构,并告诉读者如何才能高效地学习R语言. 最近遇到很多的程序员都想转行到数据分析,于是就开 ...

  7. JavaScript语言精粹 笔记01 语法 对象

    内容比较简单,只是从头梳理一下JS的知识 语法空白标识符数字字符串语句 对象对象字面量检索更新引用原型反射枚举删除减少全局变量污染  语法 1 空白 空白可能表现为格式化字符或注释的形式.空白通常没有 ...

  8. JavaScript 语言的历史

    说明:此类博客来自以下链接,对原内容做了标注重点知识,此处仅供自己学习参考! 来源:https://wangdoc.com/javascript/basic/introduction.html 1.诞 ...

  9. 林大妈的JavaScript基础知识(三):JavaScript编程(4)数组

    数组,是一段线性分配的,具有非常高性能的数据结构.简单地说,数组以连续的空间存储,通过整数地计算偏移量访问其中的元素,将读取修改的时间复杂度降低至O(1),我们称之为猝发式存取.是不是非常期待?没错, ...

随机推荐

  1. "无法启动应用程序,工作组信息文件丢失,或是已被其他用户已独占方式打开"解决办法

    当程序用ado的jet4.0方式连接mdb数据库的时候,对于设有access数据库密码的mdb的访问居然报错“无法启动应用程序,工作组信息文件丢失,或是已被其他用户已独占方式打开”. ADOConne ...

  2. 北京地铁月度消费总金额计算(Python版)

    最近业余时间在学习Python,这是那天坐地铁时突发奇想,想看看我这一个月的地铁费共多少钱,所以简单的构思了下思路,就直接开写了,没想到用Python来实现还挺简单的. 设计思路: 每次乘车正常消费7 ...

  3. WPF 获取程序路径的一些方法,根据程序路径获取程序集信息

    一.WPF 获取程序路径的一些方法方式一 应用程序域 //获取基目录即当前工作目录 string str_1 = System.AppDomain.CurrentDomain.BaseDirector ...

  4. android之AlertDialog 点击其它区域自己主动消失

    遇到一个问题记录下来,在开发中使用了AlertDialog,想点击屏幕其它区域的时候让这个dialog消失,一開始不做不论什么设置,在小米手机能够正常显示,可是在三星中却有问题.后来发现少了一个属性: ...

  5. Mesos源码分析

    Mesos源码分析(1): Mesos的启动过程总论 Mesos源码分析(2): Mesos Master的启动之一 Mesos源码分析(3): Mesos Master的启动之二 Mesos源码分析 ...

  6. Error occurred during initialization of VM java/lang/NoClassDefFoundError: java/lang/Object

    本地原来已经安装了JAVA JDK1.7并配置好了环境变量; 然后又安装了JDK8,想2个版本并存. 然后发现eclipse 打不开,闪退.然后查看环境: 发现 C:\Users\Administra ...

  7. 一致性哈希算法 - consistent hashing

    1 基本场景比如你有 N 个 cache 服务器(后面简称 cache ),那么如何将一个对象 object 映射到 N 个 cache 上呢,你很可能会采用类似下面的通用方法计算 object 的 ...

  8. MT写的对URL操作的两个方法

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. PowerShell实现文件下载(类wget)

    对Linux熟悉的读者可能会对Linux通过wget下载文件有印象,这个工具功能很强大,在.NET环境下提到下载文件大多数人熟悉的是通过System.Net.WebClient进行下载,这个程序集能实 ...

  10. SAP S4 Finance6个支持企业实时财务管理的主要创新领域

    本文将讲述下 SAP Simple Finance里面6个支持企业实时财务管理的主要创新领域. Simple Finance 在以下几个方面具有自己独特的优势: ● 更加简洁的用户体验,可以让用户在任 ...