JavaScript对象及原型链

JavaScript对象及原型链

一、JS对象

1、对象定义
js对象是引用类型,用于存储键值对
2、对象创建
(1)直接量(字面量):适用于创建单个对象,当要创建多个对象会产生大量重复代码;

var person = {
	name:'Tom',
	age:20,
}
console.log(person.age);//20

(2)工厂模式:使用函数创建,一般也少用:

function createPerson1(name,age){
	var obj = new Object();
	obj.name = name;
	obj.age = age;
	return obj;
}
var person_1 = createPerson1('Tom',30);
console.log(person_1);//{name: "Tom", age: 30}

(3)构造函数模式:

  • 系统自带构造函数:
var person_3 = new Object();
person_3.name = 'Tony';
console.log(person_3.name);
  • 自定义构造函数:
function Teacher(name,age){
	this.name = name;
	this.age = age;
}
var teacher_1 = new Teacher('Tom',20);
console.log(teacher_1);//Teacher {name: "Tom", age: 20}

(4)new创建:使用默认构造函数new创建对象

var teacher_2 = new Object();
console.log(teacher_2);//{}

(5)Object.create()创建:括号内参数是对象的原型:

var a = Object.create(new Array(1,2,3,4,5));
console.log(a);//Array {}
console.log(a.length);//5
console.log(a.sort());//Array {0: 1, 1: 2, 2: 3, 3: 4, 4: 5}
var b = Object.create(new String('null'));
console.log(b[3]);//l

3、对象方法:
(1)valueOf():返回当前对象的原始值,但是Math、Error对象是没有valueOf()方法的;

  • Array:返回数组实例
  • Boolean:返回布尔值
  • Date:返回截止目前的毫秒值
  • 函数:函数本身
  • Number:数字值
  • Object:对象本身
  • String:字符串本身

(2)toString()方法:返回当前对象对应的字符串格式:

  • Array:将数组转换为字符串并连接起来使用逗号分隔
  • Boolean:true返回"true",否则"false"
  • Date:返回日期文本表示样式
  • Error:返回一个包含错误信息的字符串
  • 函数:返回function functionName() { [native code] }
  • Number:范湖数字的文本表示样式
  • String:返回String对象值
  • Object:返回object Object

(3)valueOf和toString的区别:

  • valueOf偏向于计算,toString偏向于显示
  • 进行强制转换字符串时优先调用toString,强转为数字时优先调用valueOf()
  • 在有运算符的情况下,valueOf()的优先级高于toString()

4、对象属性
(1)定义和修改属性Object.defineProperty():

  • 语法:Object.defineProperty(obj, prop, descriptor)
  • 参数:obj 需要定义属性的对象;obj 需要定义属性的对象;descriptor 需被定义或修改的属性的描述符,是一个对象形式;
var person = {
    name: 'yourname', 
    age: 10
};
Object.defineProperty(person, "sex", {
	value: "male",
	enumerable: false			//不可枚举
});

(2)检测属性:

  • in:检查一个属性是否属于某个对象,包括继承来的属性;
var obj = {
	name:'Tom',
	age:20
}
console.log('age' in obj);//true
console.log('say' in obj);//false
  • hasOwnProperty():检查一个属性是否属于某个对象自有属性,不包括继承来的属性;
var person = {
    name:'yourname', 
    age:10
};
person.__proto__.LastName = "deng"; //让person继承一个LastName属性
Object.defineProperty(person, "sex", {
			value: "male",
			enumerable: false			//不可枚举
});
console.log(person.hasOwnProperty('name'));     //true
console.log(person.hasOwnProperty('sex'));      //true
console.log(person.hasOwnProperty('toString')); //false
console.log(person.hasOwnProperty('LastName')); //false
  • propertyEnumerable():是hasOwnProperty()的增强版,检查一个属性是否属于某个对象自有属性,不包括继承来的属性,且该属性可枚举;
var person = {
    name:'yourname',
    age:10
};
person.__proto__.LastName = "deng"; //让person继承一个LastName属性
Object.defineProperty(person, "sex", {
			value: "male",
			enumerable: false	//不可枚举
});
console.log(person.propertyIsEnumerable('name'));     //true
console.log(person.propertyIsEnumerable('sex'));      //false
console.log(person.propertyIsEnumerable('toString')); //false
console.log(person.propertyIsEnumerable('LastName')); //false

(3)存取器属性getter、setter,可以替代属性值

  • 由getter、setter定义的属性成为存取器属性
  • 一般仅一个值的属性为数据属性
  • 设置存取器属性的值使用setter,可写
  • 查询存取器属性值用getter,可读
myObj.b = 5;
console.log(myObj.b); //3,属性打印仍然为3

var myObj = {
	a: 2,
	get b() {
		if(this._b_ == undefined) return 3;
		else return this._b_;
	},
	set b(val) {
		this._b_ = val;
	}
};
console.log(myObj.b); //3
myObj.b = 100;
console.log(myObj.b); //100
var myobj = {
    //数据属性
    myname:'yourname',
    birthday:'1983-05-17',
    get myage(){
        return (new Date().getFullYear()) - new Date(this.birthday).getFullYear();
    },
    set myage(value){
        this.birthday = value;
    }
};
myobj.myage = '1998-08-22';//相当于调用了set myage(value)方法
console.log(myobj.myage);//相当于调用了个get myage()方法

(4)删除属性:delete

  • 严格模式下,不能删除变量,但是能够删除对象内部的属性
  • 仅能删除自有属性,不能删除继承属性
  • 删除成功或删除了不存在属性返回true
  • 删除继承属性时,返回的是true,但只是表面删除,其原型中该属性依然存在

5、序列化对象(对象与字符串的转换)
(1)对象转换成字符串:JSON.stringify()
(2)字符串转换为对象:JSON.parse()——此时的字符串要是JSON格式

var obj = {
	name:'Tom',
	age:20,
	classroom:[
		'0001',
		'0121',
		'0010'
	]
}
var str = JSON.stringify(obj);
console.log(str,typeof str);
//{"name":"Tom","age":20,"classroom":["0001","0121","0010"]} string
var obj_1 = JSON.parse(str);
console.log(obj_1,typeof obj_1);
//{name: "Tom", age: 20, classroom: Array(3)} "object"

二、原型链

1、原型
(1)定义:是function对象的一个属性,定义了构造函数构造出来的公共祖先,通过该构造函数创建的对象,可以继承他的原型的属性和方法;原型也是对象;

(2)原型属性:

  • prototype:构造函数的原型
  • proto:指向构造函数的prototype,是创建构造函数时自动添加的对象
  • constructor:指向构造函数本身

声明一个函数,则这个函数默认会有一个属性叫 prototype ;而且浏览器会自动按照一定的规则创建一个对象, 这个对象就是这个函数的原型对象,prototype属性指向这个原型对象; 这个原型对象有一个属性叫constructor 执行了这个函数

  • 注意:原型对象默认只有属性–constructor。 其他都是从Object继承而来,暂且不用考虑。
function Person (username){
      this.username = username;
      this.say = function(){
      console.log(this.username);
      }
   }
console.log(Person.__proto__ === Function.prototype);//true
console.log(Person.prototype.__proto__ === Object.prototype);//true

代码图解:原型链

2、原型的使用:

  • 可以在原型上扩展属性或者方法,包括系统内置构造函数;
  • 原型给了我们一个修改内置构造函数的接口和机会
  • 方法劫持call、apply、bind

示例:

function Person(username){
      this.username = username;
   }
    //在原型上增加属性或方法
Person.prototype.say = function(){
      console.log('11111');
   }
Person.prototype.a = 200;
var p1 = new Person('mei');
console.log(p1);
p1.say();//11111
console.log(p1.a);//200
//修改系统内置的构造函数的属性或方法
var arr = new Array(1,2,3);
Array.prototype.sum = function(){
      console.log(this);
      var sum = 0;
      for(var i = 0;i<this.length;i++){
           sum +=this[i];
       }
      return sum;
  }
Array.prototype.max = function(){
      console.log(this);
      var max = this[0];
      for(var i = 0;i<this.length;i++){
          (max < this[i])&&(max = this[i]);
      }
      return max;
  }
console.log(arr.sum());//6
var arr1 = [100,200,300];
console.log(arr1.sum());//600
console.log(arr1.max());//300
var str = new String('aaa');
console.log(str);//String{'aaa'}
//Math就是一个对象,没有构造函数,不需要new
console.log(Math.max(1,2,3,9,0));//9
//改变指向
console.log(Math.max.apply(arr1,arr1));//300
  1. 改变原型对象:当改变了原型对象,constructor将不会再指向构造函数,需要指定constructor指向的对象
function Person(){}
console.log(Person.prototype);
//为构造函数指定新的原型对象
//当改变了原型对象,constructor将不会再指向构造函数,需要指定constructor指向的对象
Person.prototype = {
	name:'Tom',
	age:20,
	constructor:Person
}
console.log(Person.prototype.constructor);//Person构造函数
  1. 查看原型
    构造函数名.prototype
    对象.proto
function Person(name,age){
	this.name = name;
	this.age = age;
}
console.log(Person.prototype);//指向Person构造函数
			
Person.prototype = {
	sleep:function(){
	    console.log('sleeping');
	}
}
//更改了原型指向,没有再指定constructor
console.log(Person.prototype);//指向新的原型对象
var p1 = new Person('Tom',20);
console.log(p1.__proto__);//查看原型(此时原型是新的原型)
p1.sleep();//调用新的原型对象中的方法
  1. 通过原型创建对象

(1)不推荐的创建属性方法:在原型上创建属性,适宜在原型上创建方法

function Person(){}
Person.prototype.name = 'Tom';
Person.prototype.age = 20;
var p1 = new Person();
console.log(p1.name);//Tom
p1.__proto__.name = 'Tony';
//改变了原型上的属性值
console.log(p1.name);//Tony
var p2 = new Person();
//当改变了原型上的属性值后,再通过构造函数创建的对象访问该原型,
//该属性值是上个对象更改后的属性值
console.log(p2.name);//Tony

(2)在原型上创建方法:将相同的函数创建在原型上

function Person(name,age){
	this.name = name;
	this.age = age;
}
//将相同的函数定义在原型上
Person.prototype.sleep = function(){
	console.log('sleep');
}
var p1 = new Person('Tom',10);
p1.sleep();
var p2 = new Person('Tony',20);
p2.sleep();

(3)动态创建原型上的方法和属性:通过判断属性的类型是函数还是普通属性,将函数创建在原型上,将普通属性创建在构造函数里

function Person(name,age){
	this.name = name;
	this.age = age;
	if(typeof this.sleep  == 'function'){
		Person.prototype.sleep = function(){
			console.log('sleeping');
		}  
	}
}
var p1 = new Person('Tom',10);
p1.sleep();
var p2 = new Person('Tony',20);
p2.sleep();

3、原型链

  1. 原型链
    (1)每个对象都从它的原型继承属性,直到Object的原型指向null
    (2)原型链是将一个个原型连起来,形成一条原型继承的链,原型链的顶端是Object
    下面来看一个简单的原型链:
function Person(){
				
}
var p1 = new Person();
console.log(p1.__proto__);

简单的原型链

  1. 使用原型链实现继承关系

    (1)原型链是继承的基本思想,它例用原型让一个引用类型继承两一个引用类型的属性和方法;
    (2)改变某个构造函数的原型指向,可以控制它继承自哪个对象
    例如:

function GrandParent(){
	this.name = 'A';
}
function Parent(){
	this.name = 'B of A';
}
Parent.prototype = new GrandParent();
function Child(){
	this.name = 'C of B';
}
Child.prototype = new Parent();
var child = new Child();
console.log(child.__proto__);

该例的详细继承过程的原型链如下所示:
原型链实现继承

4、new操作

  • 创建新对象,调用构造函数,同时在堆中开辟空间将对象存入进去,并将地址保存在变量中
  • 将函数的上下文对象(作用域)中的this指向了该对象
  • 执行构造函数中的代码,通过this来添加属性和方法
  • 返回对象
    比如:
function Person(name,age){
   this.name = name;
   this.age = age;
   //创建对象中的方法
   this.say = function(){
        return this.name;
     }
   return 100;
}
//创建Person的实例化对象
var person1 = new Person('Tom',18);
console.log(person1);
//Person {name: "Tom", age: 18, say: ƒ}

new过程图解:
new过程

猜你喜欢

转载自blog.csdn.net/qq_42602282/article/details/106762231