4.1变量,作用域
Javascript变量是松散类型的本质,决定了它只是在特定的时间用于保存特定的值而已。由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期内改变。
ECMAScript变量可能包含两种不同数据类型的值:
基本类型和引用类型
基本类型就是简单的数据段 (Undefined Null Number Boolean String )基本类型是按值访问的
引用类型是那些可能由多个值构成的对象(Object)引用类型实际上是在操作对象的引用,而不是实际的对象
区别
1复制变量值
1)基本类型:会在变量对象上创建一个新值,然后把改值复制到新变量
分配的位置上 互不影响 完全独立
2)引用类型:复制的是原来对象的指针,这个指针指向存储在堆中的一个对象。复制操作结束后实际上两个变量引用同一个对象。改变其一会影响另一个变量
4.1.4检测类型
基本数据类型的检测用typeof
引用类型的检测用instanceof
6.2创建对象
1.工厂模式
function obj(name, age, job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
}
return o;
}
var person1 = obj("Nike",28,"enginner")
2构造函数模式
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name)
}
}
var person2 = new Person("Lucy",28,"enginner");
3原型模式
function Person(){}
Person.prototype.name = "Nike";
Person.prototype.age = 28;
Person.prototype.job = "Engineer";
Person.sayName = function(){
alert(this.name);
}
4组合使用构造函数和原型
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Nike","Lucy"]
}
Person.prototype = {
constructor : Person,
sayName : function(){
alert(this.name);
}
}
var person1 = new Person();
var person2 = new Person();
person2.friends.push("Lili");
console.log(person2.friends)
console.log(person1.friends)
console.log(person2.friends === person1.friends)
5动态原型模式
有其他 OO 语言经验的开发人员在看到独立的构造函数和原型时,很可能会感到非常困惑。动态原
型模式正是致力于解决这个问题的一个方案,它把所有信息都封装在了构造函数中,而通过在构造函数
中初始化原型(仅在必要的情况下),又保持了同时使用构造函数和原型的优点。换句话说,可以通过
检查某个应该存在的方法是否有效,来决定是否需要初始化原型。来看一个例子
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
if(typeof this.sayName != "function"){
Person.prototype.sayName = function(){
alert(this.name);
}
}
}
var fr = new Person("Bill",10,"student");
6寄生构造函数模式
function SpecialArray(){
var value = new Array();
value.push.apply(value, arguments);
value.toPipedString = function(){
return this.join("|");
}
return value;
}
var val = new SpecialArray("red","blue");
console.log(val instanceof SpecialArray)
in 操作符 和 hasOwnProperty()
有两种方式使用 in 操作符:单独使用和在 for-in 循环中使用。在单独使用时,in 操作符会在通
过对象能够访问给定属性时返回 true,无论该属性存在于实例中还是原型中。
由于 in 操作符只要通过对象能够访问到属性就返回 true,hasOwnProperty()只在属性存在于
实例中时才返回 true
keys()
要取得对象上所有可枚举的实例属性,可以使用 ECMAScript 5 的 Object.keys()方法。这个方法
接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var keys = Object.keys(Person.prototype);
alert(keys); //"name,age,job,sayName"
var p1 = new Person();
p1.name = "Rob";
p1.age = 31;
var p1keys = Object.keys(p1);
alert(p1keys); //"name,age"
****原型的动态性****
尽管可以随时为原型添加属性和方法,并且修改能够立即在所有对象实例中反映出来,但如果是重
写整个原型对象,那么情况就不一样了。我们知道,调用构造函数时会为实例添加一个指向最初原型的
[[Prototype]]指针,而把原型修改为另外一个对象就等于切断了构造函数与最初原型之间的联系。
请记住:实例中的指针仅指向原型,而不指向构造函数
function Person(){
}
var friend = new Person();
Person.prototype = {
constructor: Person,
name : "Nicholas",
age : 29,
job : "Software Engineer",
sayName : function () {
alert(this.name);
}
};
friend.sayName(); //error
proto
继承是面向对象编程的最最基础的概念,本文主要讲解JS中继承的实现方式及原理。
将共享方法抽象到函数prototype中。
对于共享属性/方法,没必要每个对象都复制一份,只需要能引用到这个属性就可以了,而这与prototype的思路正好相同。