学习笔记1-->> http://www.mytju.com/classcode/news_readNews.asp?newsID=226
Context
上下文,这是面向对象语言的共通的特性,但是javascript里是很极端的。
Context是通过this变量工作的,this变量始终指向一个对象(代码当前在哪运行的那个对象)。
即使是全局Context,this变量也是指向window对象的。
<script> var obj = { yes: function(){ // this == obj this.val = true; }, no: function(){ this.val = false; } }; // We see that there is no val property in the 'obj' object alert( obj.val == null );
// We run the yes function and it changes the val property // associated with the 'obj' object //当前Context是obj变量,所以this指向它,改变的是它的属性。 obj.yes(); alert( obj.val == true );
// However, we now point window.no to the obj.no method and run it //Context变为window对象,改变的是它的属性 window.no = obj.no; window.no();
// This results in the obj object staying the same (as the context was // switched to the window object) //所以obj的val属性是true alert( obj.val == true );
// and window val property getting updated. //window的val属性是false alert( window.val == false ); </script>
四个结果全是true。
这样变更Context太麻烦,javascript提供了两个方法,使这个过程更容易理解和实现。
<div id="main">sssssssssssssssss</div> <script> // A simple function that sets the color style of its context function changeColor( color ) { this.style.backgroundColor = color; } // Calling it on the window object, which fails, since it doesn't // have a style object //当前是window对象,此句会失败, changeColor( "white" );
// Find the element with an ID of main var main = document.getElementById("main"); // Set its color to black, using the call method // The call method sets the context with the first argument // and passes all the other arguments as arguments to the function //使用call方法,第一个参数设置Context changeColor.call( main, "black" );
// A function that sets the color on the body element function setBodyColor() { // The apply method sets the context to the body element // with the first argument, the second argument is an array // of arguments that gets passed to the function //使用apply方法,第一个参数设置Context,第二个参数是参数数组 changeColor.apply( document.body, arguments ); } // Set the background color of the body to black setBodyColor( "yellow" ); </script>
整个页面背景是黄色,div的背景是黑色。需要注释掉changeColor( "white" );
面向对象基础
Object Object是javascript的基础,事实上,everything都是Object。 在大部分基本层面来说,Object以属性集合的形式存在,类似于其他语言中的hash结构。
<script> // Creates a new Object object and stores it in 'obj' var obj = new Object(); // Set some properties of the object to different values //设置属性 obj.val = 5; obj.click = function(){ alert( "hello" ); }; // Here is some equivalent code, using the {…} shorthand // along with key-value pairs for defining properties //更简洁的声明方式 var obj = { // Set the property names and values use key/value pairs val: 5, click: function(){ alert( "hello" ); } }; </script>
Object Creation 与其他面向对象语言不通,javascript中没有class类的概念。 在javascript中,Object可以创建Object,可以从其他Object继承,这整个概念称为“prototypal inheritance”(原型继承)
任何function也可以当作Object对待。
<script> // A simple function which takes a name and saves // it to the current context function User( name ) { this.name = name; } // Create a new instance of that function, with the specified name var me = new User( "My Name" ); // We can see that its name has been set as a property of itself //属性已经改变了 alert( me.name == "My Name" ); // And that it is an instance of the User object alert( me.constructor == User );
// Now, since User() is just a function, what happens // when we treat it as such? User( "Test" ); // Since its 'this' context wasn't set, it defaults to the global 'window' // object, meaning that window.name is equal to the name provided //没有指定,则this指向了window对象。 alert( window.name == "Test" ); </script>
结果都是true。
constructor属性,每个Object都有,指向创建它的function。
OK,下面看看如何创建一个新的Object,但不用名字。
<script> // Create a new, simple, User object function User() {} // Create a new User object var me = new User();
// Also creates a new User object (from the // constructor reference of the first) var you = new me.constructor();
// We can see that the constructors are, in fact, the same alert( me.constructor == you.constructor ); </script>
结果是true。
现在已经知道如何创建简单的对象了,下面看一下如何增加属性和方法。
Public Methods 这里要了解一下prototype属性,它包含一个对象,对于所有Object的副本来说,这个对象都指向Object。 prototype的任何属性都可以被Object的所有实例访问。 所以,只要给prototype追加属性,那么原始Object的所有实例都拥有了这个属性,这个属性就是Public的了。
<script> // Create a new User constructor function User( name, age ){ this.name = name; this.age = age; } // Add a new function to the object prototype //给prototype追加属性来给User追加方法。 User.prototype.getName = function(){ return this.name; }; // And add another function to the prototype // Notice that the context is going to be within // the instantiated object User.prototype.getAge = function(){ return this.age; }; // Instantiate a new User object var user = new User( "Bob", 44 ); // We can see that the two methods we attached are with the // object, with proper contexts alert( user.getName() == "Bob" ); alert( user.getAge() == 44 ); </script>
Private Methods 私有方法和变量,只能被其他私有方法,私有变量和特权方法(privileged methods)访问的。 它们只能在Ojbect内部访问,外部不可以。 这个技术主要基于Douglas Crockford的工作,它的网站有详细的文档。 http://javascript.crockford.com/ http://javascript.crockford.com/private.html
<script> // An Object constructor that represents a classroom function Classroom( students, teacher ) { // A private method used for displaying all the students in the class function disp() { alert( this.names.join(", ") ); } // Store the class data as public object properties this.students = students; this.teacher = teacher; // Call the private method to display the error disp(); } // Create a new classroom object var class = new Classroom( [ "John", "Bob" ], "Mr. Smith" ); // Fails, as disp is not a public property of the object //下面这句是错误的,不能访问disp方法。 class.disp(); </script>
Privileged Methods 特权方法还是Douglas Crockford这位大哥搞的,用来查看和操纵私有变量的Public方法。
<script language="javascript"> // Create a new User object constructor function User( name, age ) { // Attempt to figure out the year that the user was born var year = (new Date()).getFullYear() – age; // Create a new Privileged method that has access to // the year variable, but is still publically available this.getYearBorn = function(){ return year; }; } // Create a new instance of the user object var user = new User( "Bob", 44 );
// Verify that the year returned is correct alert( user.getYearBorn() == 1962 ); </script> 我运行怎么没反应??
特权方法是动态生成的,因为它是运行时动态追加到Object的。
下面看一下动态生成的方法能干什么……
<script language="javascript"> / Create a new user object that accepts an object of properties function User( properties ) { // Iterate through the properties of the object, and make sure // that it's properly scoped (as discussed previously) //遍历所有,动态生成get方法和set方法。 for ( var i in properties ) { (function(){ // Create a new getter for the property this[ "get" + i ] = function() { return properties[i]; }; // Create a new setter for the property this[ "set" + i ] = function(val) { properties[i] = val; }; })(); } } // Create a new user object instance and pass in an object of // properties to seed it with var user = new User({ name: "Bob", age: 44 }); // Just note that the name property does not exist, as it's private // within the properties object //name属性是私有的,不能直接访问。 alert( user.name == null );
// However, we're able to access its value using the new getname() // method, that was dynamically generated //但是,我们可以通过get方法访问。 alert( user.getname() == "Bob" );
// Finally, we can see that it's possible to set and get the age using // the newly generated functions //还可以通过set方法设置值 user.setage( 22 ); alert( user.getage() == 22 ); </script>
哇塞,根据动态的变量创建代码,简直不可相信,太有用了……
Static Methods 静态方法背后的实质和其他正常的function是完全一致的,没什么不一样。 主要的不同就是:这个function是作为Object的一个静态属性存在的。 作为一个属性,Object的实例是不能访问的,只有在Object同样的Context里才能访问。 这和其他语言的静态方法有点像……
实际上,这样写代码的唯一优点是保持Object的namespace clean.
// A static method attached to the User object User.cloneUser = function( user ) { // Create, and return, a new user return new User( // that is a clone of the other user object user.getName(), user.getAge() ); };
静态方法是我们遇到的第一个,纯粹是组织关系用的方法。
|