深入学习javascript面向对象及高级特性

    技术2022-05-20  53

    javascript对象(Objects):

         JavaScript 对象是词典,对象只是一组名称/值对,就是说,将 JavaScript 对象视为包含字符串关键字的词典,只接受字符串关键字。我们可以使用熟悉的“.”(点)运算符或“[]”运算符,来获得和设置对象的属性。JavaScript 对象不必预先声明属性,如果没有该名称的属性,该属性将被直接添加到对象,记住JavaScript对象是词典。

     

    var myObject = new Object();myObject.creatorTime = new Date();alert(myObject.creatorTime);  

     

    var myObject = {}; // equivalent to new Object()myObject[“creatorTime”] = new Date();alert(myObject[“creatorTime”]);

    var myObject = { “creatorTime”: new Date() };alert(myObject.creatorTime);

     

    JavaScript 函数:(Functions)

    JavaScript 函数和对象差别很模糊,JavaScript 函数实际上是具有与它关联的可执行代码的对象。function func(x) {    alert(x);}func("test");

    var func = function(x) {    alert(x);};func("test");

    var func = new Function(“x”, “alert(x);”);func(“test”);

    可以说函数是对象,您可以像对其他任何 JavaScript 对象一样,在函数中设置或添加属性function sayHi(x) {    alert(“Hi, “ + x + “!”);}sayHi.text = “Hello World!”;sayHi[“text2”] = “Hello World... again.”;

    alert(sayHi[“text”]); // displays “Hello World!”alert(sayHi.text2); // displays “Hello World... again.”

     

    作为对象,函数还可以赋给变量、作为参数传递给其他函数、作为其他函数的值返回,并可以作为对象的属性或数组的元素进行存储等等var obj = { “toString” : function() { return “This is an object.”; } };alert(obj);//This is an object

    var arr = [];arr[0] = function(x) { return x * x; };arr[1] = arr[0](2);arr[2] = arr[0](arr[1]);alert(arr[2]); //16

    向对象添加方法:

    var myDog = {    "name" : "Alan",    "bark" : function() { alert("Alan liu!"); },    "displayFullName" : function() {        alert(this.name + " is a good man!");    },    "chaseMrPostman" : function() {         return "haha";    }    };myDog.displayFullName(); // alan is a good manmyDog.bark(); //Alan liu!alert(myDog.chaseMrPostman())//haha

     

    this和with:(this & this)

     

    通过不同对象调用“this”时,它的值也会更改以便指向相应的对象function displayQuote() {    alert(this.memorableQuote);    }

    var williamShakespeare = {    "memorableQuote": "It is williamShakespeare.",     "sayIt" : displayQuote};

    var markTwain = {    "memorableQuote": "It is markTwain.",     "sayIt" : displayQuote};

    var oscarWilde = {    "memorableQuote": "It is oscarWilde." ,    "sayIt" : displayQuote};

    williamShakespeare.sayIt(); markTwain.sayIt();

    displayQuote.call(oscarWilde); 表示的是将函数作为对象的方法进行调用的另一种方式。请记住,JavaScript 中的函数是对象。每个函数对象都有一个名为 call 的方法,它将函数作为第一个参数的方法进行调用。就是说,作为函数第一个参数传递给 call 的任何对象都将在函数调用中成为“this”的值。这一技术对于调用基类构造函数来说非常有用

    有一点需要记住,绝不要调用包含“this”(却没有所属对象)的函数。否则,将违反全局命名空间,因为在该调用中,“this”将引用全局对象,而这必然会给您的应用程序带来灾难。例如,下面的脚本将更改 JavaScript 的全局函数 isNaN 的行为。一定不要这样做!function displayQuote() { alert("NaN is NaN: " + isNaN('qw'));}displayQuote();function x() {    this.isNaN = function() {         return "not anymore!";    };}x();alert("NaN is NaN: " + isNaN('qw'));

     

    with 语句 为一个或一组语句指定默认对象。 用法:with (<对象>) <语句>; with 语句通常用来缩短特定情形下必须写的代码量。在下面的例子中,请注意 Math 的重复使用: x = Math.cos(3 * Math.PI) + Math.sin(Math.LN10); y = Math.tan(14 * Math.E); 当使用 with 语句时,代码变得更短且更易读: with (Math) {    x = cos(3 * PI) + sin(LN10);    y = tan(14 * E); }

     

    JavaScript 构造函数(Constructor)

     

    Functions which are used to initialize objects are called constructors.

    JavaScript 中,本来就没有类。与访问类最近似的方法是定义构造函数: function MyConstructor(name) {    this.name = name;    this.respondTo = function(name) {        if(this.name == name) {            alert(“Woof”);                }    };}

    var spot = new MyConstructor(“Spot”);//“new”运算符执行的操作很简单。首先,它创建一个新的空对象。然后执行紧随其后的函数调用,将新的空对象设置为该函数中“this”的值。这个语句的作用和下面两句一样:var spot = {};  DogConstructor.call(spot, “Spot”);spot.respondTo(“Rover”); spot.respondTo(“Spot”); // Woof

     

    原型(Prototype):       Objects contain a hidden link property. This link points to the prototype member of the constructor of the object       使用 JavaScript 的面向对象编程中,原型对象是个核心概念。在 JavaScript 中对象是作为现有示例(即原型)对象的副本而创建的,该名称就来自于这一概念。此原型对象的任何属性和方法都将显示为从原型的构造函数创建的对象的属性和方法。可以说,这些对象从其原型继承了属性和方法。

     

          在 JavaScript 中,每个函数都有名为“prototype”的属性,用于引用原型对象。此原型对象又有名为“constructor”的属性,它反过来引用函数本身,这是一种循环引用。

        

    下面几行代码结果可以体现出他们之间的对应关系:

     var spot = new MyConstructor("Spot");alert(MyConstructor.prototype.isPrototypeOf(spot)); //truealert(spot.constructor == MyConstructor.prototype.constructor);//truealert(spot.constructor == MyConstructor);//truealert(spot.hasOwnProperty("constructor"));//falsealert(MyConstructor.prototype.hasOwnProperty("constructor"));//true

     

     

       hasOwnProperty 和 isPrototypeOf 方法的调用,它们不是来自 MyConstructor.prototype。实际上,在 MyConstructor.prototype 和 MyConstructor实例中还可以调用其他方法,比如 toString、toLocaleString 和 valueOf,但它们都不来自 MyConstructor.prototype。就像java 中的 Object 充当所有类的最终基类一样,JavaScript 中的 Object.prototype 是所有原型的最终基础原型。(Object.prototype 的原型是 null。)

     

    看下面代码的运行结果,可以得出以下结论:

     

    继承原型对象的对象上可以立即呈现对原型所做的更改,即使是在创建这些对象之后。如果在对象中定义了属性/方法 X,则该对象的原型中将隐藏同名的属性/方法。例如,通过在 Mobile.prototype 中定义 toString 方法,可以改写 Object.prototype 的 toString 方法。更改只沿一个方向传递,即从原型到它的派生对象,但不能沿相反方向传递您需要绑定到类而不是实例的属性或方法,也就是静态属性和方法,可用通过构造函数中设置静态方法和属性,直接将它们添加到类中,这些静态属性和方法实例不可调用。

     

    function Mobile() { }

    var rover = new Mobile();var spot = new Mobile();

    Mobile.prototype.getBrand= function() {    return "moto";};Mobile.prototype.color= "red";

     

    Mobile.price='2001'

     

    alert(Mobile.price);//2001

    alert(rover.price);//undefined

     

     

    alert(rover.getBrand());//motoalert(rover.color);//red

     

    spot.getBrand = function() {    return "nokia";};spot.color= "black";

     

    alert(spot.getBrand()); //nokiaalert(spot.color); //"black"

     

    alert(rover.getBrand());//motoalert(rover.color);//red

    闭包:(Closure)

           Functions can be defined inside of other functions. The inner function has access to the vars and parameters of the outer function. If a reference to an inner function survives (for example, as a callback function), the outer function's vars also survive.

     

     

     

    JavaScript 的更高级功能之一是它支持闭包,闭包是当内部函数绑定到它的外部函数的本地变量时所发生的运行时现象。

    定义一个筛选大于**的数字函数

     

    function filter(pred, arr) {

        var len = arr.length;

        var filtered = []; // shorter version of new Array();

     

        for(var i = 0; i < len; i++) {

            var val = arr[i];

     

            if(pred(val)) {

                filtered.push(val);

            }

        }

        return filtered;

    }

     

    var someRandomNumbers = [12, 32, 1, 3, 2, 2, 234, 236, 632,7, 8];

     

     

    function makeGreaterThanPredicate(lowerBound) { return function(numberToCheck) { return (numberToCheck > lowerBound) ? true : false; }; }

    var greaterThan10 = makeGreaterThanPredicate(10); var greaterThan100 = makeGreaterThanPredicate(100); alert(filter(greaterThan10, someRandomNumbers)); alert(filter(greaterThan100, someRandomNumbers)); 通过观察函数 makeGreaterThanPredicate 返回的内部匿名函数,可以发现,该匿名内部函数使用 lowerBound,后者是传递给 makeGreaterThanPredicate 的参数。按照作用域的一般规则,当 makeGreaterThanPredicate 退出时,lowerBound 超出了作用域!但在这里,内部匿名函数仍然携带 lowerBound,甚至在 makeGreaterThanPredicate 退出之后的很长时间内仍然如此。这就是我们所说的闭包:因为内部函数关闭了定义它的环境(即外部函数的参数和本地变量)。

     

    在 JavaScript 中,闭包最有趣的用途之一是模拟类的私有变量 function Person(name, age) { this.getName = function() { return name; }; this.setName = function(newName) { name = newName; }; this.getAge = function() { return age; }; this.setAge = function(newAge) { age = newAge; }; var sex; this.sex= function() { return sex; }; this.sex= function(newsex) { sex= sex; }; }

     

     var ray = new Person(“Alan”, 31);

    alert(ray.name);//undefined ray.setSex('male'); alert(ray.getSex());//male alert(ray.getName());//Alan alert(ray.getAge());//31 ray.setName(“Younger Alan”); ray.setAge(25); alert(ray.getName() + “ is now “ + ray.getAge() + “ years old.”);//Younger Alan is now 25 Person.prototype.testMethod = function() { alert(this.name);undefined alert(this.getName());//Younger Alan }; ray.testMethod() 继承(Inheritance):    JavaScript 非常灵活,可以有很多从类继承的方式,下边提供一类,JavaScript是使用的原型来做继承的,而不是经典的面向对象式的继承自父类 function Pet(name) {     this.getName = function() { return name; };     this.setName = function(newName) { name = newName; }; } Pet.prototype.toString = function() {     return "This pet’s name is: " + this.getName(); }; var parrotty = new Pet("Beike"); alert(parrotty);//Beike function Dog(name, age){     Pet.call(this, name);     this.getAge = function() { return age};     this.setAge = function(newAge) { age= newage}; } Dog.prototype = new Pet(); Dog.prototype.constructor = Dog; Dog.prototype.toString = function() {     return "This dog's name is: " + this.getName() + ", and it's Age is: " + this.getAge(); }; var dog = new Dog(Heibie,3); alert(dog);//This dog's name is:Heibei,and it'is Age is 3 alert(dog instanceof Dog);//true alert(dog instanceof Pet);//ture alert(dog instanceof Object);//true 命名空间(Namespace): JavaScript 没有任何特定语言功能来支持命名空间,但很容易使用对象来模拟命名空间。如果要创建一个 JavaScript 库,则可以将它们包装在命名空间内,而不需要定义全局函数和类 var csdn= {}; csdn.alan = {}; csdn.alan .Pet = function(name) { // code }; csdn.alan .Pet.prototype.toString = function() { // code }; var pet = new csdn.alan .Pet("ALAN"); Or : var alias= csdn.alans;var pet = new alias .Pet("ALAN"); 更多学习:http://www.crockford.com/javascript/

     


    最新回复(0)