最近在学习JavaScript面向对象,写下自己的理解及相关资料,以备查阅。
一.面向对象中涉及的相关几个概念
1.作用域
所谓作用域,就是说属性和函数的可访问范围。在JavaScript中,作用域分为两种。全局作用域和局部作用域。
所有没有var 声明 或 定义于最外层函数和最外层函数外面即为全局作用域。也就是定义可以随意调用。
自定义函数内部用var声明的为局部作用域。
var num = 1; //全局作用域 window.onload = function() { //最外层为全局作用域 var age = 18; function turn() { //局部作用域,内部用var声明的只能被turn读取 sex = "男"; //未用var声明,为全局变量(可能只想用作局部,这样会出现bug,不推荐) var name = "刘某"; //局部变量 function test() { var data = "好"; var name = "王某"; console.log(name) //王某 }; console.log(name) //刘某 } }
需注意的是 读取属性(变量)时是先在最近的作用域中查找,没有就往上查找。最后查找全局,未定义则报错 undefined。
2.闭包
在JavaScript中,一个函数自带有作用域。一函数嵌套在另一函数内,内部函数可以访问到外部函数的属性,但外部函数和其他函数访问不到内部函数,为了解决这问题。闭包应运而生。
闭包的定义就是函数内部与其他函数连接的桥梁(常用return指向)。
function test(){ var n = 2; //定义为局部变量 外部函数不能访问 function f2(){ console.log(n); } return f2; //用return 返回 } var result=test(); result(); // 2 外部可以得到值
3. this指向
var name = "二货"; //全局 指向window function fooCoder(x) { this.x = x; } fooCoder(2); //函数调用,this指向window var person = { name : "foocoder", hello : function(sth){ console.log(this.name + " says " + sth); } }; person.hello("hello world"); //对象调用时,this指向对象本身(Person) function Foo(name,color) { this.name=name; this.color=color; } var cc=new Foo("liuxing","yellow"); //调用构造函数时,this指向生成的实例(cc) var persone = { name : "foocoder", hello : function(sth){ var that = this; var sayhello = function(sth) { console.log(that.name + " says " + sth); //函数内部this指向window(一说为JavaScript设计有误) }; sayhello(sth); } } person.hello("hello world"); //foocoder says hello world
总结如下(这是博客园某博主总结的,一时找不到该博客,感谢。)
1.当函数作为对象的方法调用时,this指向该对象。
2.当函数作为淡出函数调用时,this指向全局对象(严格模式时,为undefined)
3.构造函数中的this指向新创建的对象
4.嵌套函数中的this不会继承上层函数的this,如果需要,可以用一个变量保存上层函数的this。
二.javascript OOP
在javascript没有类的概念。实现继承功能的方法一般是利用原型(prototype)。今天先更到这。等理解稍透彻再来重写。
// 声明 Animal 对象构造器 function Animal() {} // 将 Animal 的 prototype 属性指向一个对象, // 亦可直接理解为指定 Animal 对象的原型 Animal.prototype = { name: "animal", weight: 0, eat: function() { alert( "Animal is eating!" ); } } // 声明 Mammal 对象构造器 function Mammal() { this.name = "mammal"; } // 指定 Mammal 对象的原型为一个 Animal 对象。 // 实际上此处便是在创建 Mammal 对象和 Animal 对象之间的原型链 Mammal.prototype = new Animal(); // 声明 Horse 对象构造器 function Horse( height, weight ) { this.name = "horse"; this.height = height; this.weight = weight; } // 将 Horse 对象的原型指定为一个 Mamal 对象,继续构建 Horse 与 Mammal 之间的原型链 Horse.prototype = new Mammal(); // 重新指定 eat 方法 , 此方法将覆盖从 Animal 原型继承过来的 eat 方法 Horse.prototype.eat = function() { alert( "Horse is eating grass!" ); } // 验证并理解原型链 var horse = new Horse( 100, 300 ); console.log( horse.__proto__ ); console.log( Horse.prototype.__proto__ === Mammal.prototype ); console.log( Mammal.prototype.__proto__ === Animal.prototype ); //对象的_proto_来实现对原型的隐式引用 function Person(age){ this.age=age; } var b=new Person("sss"); //验证构造出来的函数_proto_属性是否指向构造器的prototype console.log(b.__proto__ === Person.prototype); //原型本身是一个Object对象,所以他的隐式引用指向了Object构造器的prototype属性 console.log(Person.prototype.__proto__ === Object.prototype); //构造器Person本身是一个函数对象 console.log(Person.__proto__ === Function.prototype) //原型链 function Nperson(){} Nperson.prototype={ name:"刘星星", age:"89", num: function () { console.log(1) } } //调用原型的属性为函数时 加上() Nperson.prototype.num(); function Mperson(){} //将新构造器的原型指向已有的构造器 它原型是指向的函数 它隐式调用{原型的原型}为指向函数{对象}的几个属性 name age //创建了Mperson和Nperson的原型链 Mperson.prototype = new Nperson(); console.log(Mperson.prototype.__proto__); Mperson.prototype.num(); //使用Horse对象构造器 function Horse(height,width){ this.name = "liuxingxing"; this.height = height; this.width = width; } //将多个函数{函数的属性}链接起来 实现原型链{属性在几个函数里都可取到} Horse.prototype = new Mperson(); console.log(Horse.prototype.num); //修改原属性 不会替换之前的属性 Horse.prototype.num="asdasd"; console.log(Horse.prototype.num); //验证下原型链 var acc=new Horse(200,500); console.log(Horse.prototype.age); //acc.__proto__ 等同于 Horse.prototype console.log(acc.__proto__ === Horse.prototype); console.log(Horse.prototype.__proto__ === Mperson.prototype); console.log(Mperson.prototype.__proto__ === Nperson.prototype); document.write(Mperson.prototype.__proto__.name); // 闭包 实现信息隐藏 function User(pwd) { //定义私有属性 var password = pwd; function getPassword() { // 返回了闭包中的 password return password; } //特权函数声明,用于该对象其他公有方法能通关特定方向访问到私有成员 this.passwordSer = function () { return getPassword() } } //公有成员声明 User.prototype.accd= function (pwd) { return this.passwordSer() === pwd; } //验证隐藏性 var u = new User("liuxingxing"); //公有的可以访问到 console.log(u.accd("liuxingxing")); //私有的属性不能访问到 console.log(u.password)