javascript-对象及应用

一、初识对象

现实世界的对象:具体的事物,由特征(名词:描述这个对象的)和行为(动词:具体做的事) 组成

程序中的对象:是对现实世界中事物的抽象, 由属性和方法组成 -- 成员

scss 复制代码
函数和对象的区别:
  函数:可以封装一段代码
  对象:封装一组属性和方法

函数与方法的区别:
  函数:独立存在,调用时通过函数名调用  fn();
  方法 :属于对象的函数,称之为 对象的方法  hero.attack( );


区分 静态方法和实例方法:
直接添加到类上的是静态方法: 静态方法通过类名调用
直接添加到类的原型上的是实例方法: 实例方法通过实例调用

function AClass(){}  // 定义一个类
AClass.staticMethod = function(){alert("staticMethod")} // 给这个类添加静态方法
AClass.staticMethod() // 静态方法通过类名调用

AClass.prototype.instanceMethod = function(){alert("instanceMethod")} // 给这个类添加实例方法
var a = new AClass(); // 创建一个实例(创建一个对象)
a.instanceMethod(); // 实例方法通过类的实例调用

二、创建对象的方式

1.对象字面量{}

js 复制代码
var student = { name: '张飞', age: 18, gender: '男',
  sayHi: function () { alert('hello'); }
}
// 多个不同的属性 使用,逗号分割 

2.new Object()构造函数

js 复制代码
new 的方式调用构造函数

var hero = new Object();    // 创建了一个空的对象, new Object()等同于对象字面量{}
hero.name = '黄忠'; 			// 动态的增加属性 
hero.weakon = '弓箭';
hero.equipment = ['头盔', '盔甲', '靴子'];
hero.attack = function () {
    console.log(this.name + ':射箭');
}

3.工厂方法 批量创造对象

js 复制代码
function createHero(name, age, gender, blood) {
    var hero = new Object();	// 定义一个空对象
    hero.name = name;
    hero.age = age;
    hero.gender = gender;
    hero.blood = blood;
    hero.attack = function () {
        console.log(this.name + ':攻击');
    }
    hero.run = function () {
        console.log(this.name + ':加速跑');
    }
    return hero;	// 返回对象参数   和自定义构造函数比,多了2行代码
}

var hero01 = createHero('黄忠', 18, '男', 100);
var hero02 = createHero('刘备', 18, '男', 100);
console.log(hero01);
console.log(hero02);

4.自定义构造函数

帕斯卡命名,第一个单词的第一个字母大写

调用: new 关键字 调用 构造函数, 通过 一个变量接收 返回值

js 复制代码
function Hero(name, age, gender, blood) {
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.blood = blood;
    this.attack = function () {
        console.log(this.name + ':攻击');
    }
    this.run = function () {
        console.log(this.name + ':加速跑');
    }
}

var hero01 = new Hero('黄忠', 18, '男', 100);
var hero02 = new Hero('刘备', 18, '男', 100);
console.log(hero01);
console.log(hero02);

// this 动态的给对象增加成员,this 指向了当前对象

在自定义构造函数中,new 关键字的执行过程

scss 复制代码
var p1=new Person();
1、在内存中创建了一个空的对象 (我们把这个对象称之为Person构造函数的实例)-p1
2、让构造函数中的this 指向刚刚创建的对象(创建一个内部对象,将this指向该实例(_p1))
3、执行构造函数中的代码,在构造函数中设置属性和方法(其中,操作this的部分就是操作了该实例(_p1))
4、 返回了当前对象,返回值:
  a、如果函数没有返回值(没有return语句),那么就会返回构造函数的实例(p1)
  b、如果函数返回了一个基本数据类型的值,那么本次构造函数的返回值是该实例(_p1)
    function Fn(){ return 5;} 
    var f1 = new Fn();
    console.log(f1); // Fn {}
  c、如果函数返回了一个复杂数据类型的值,那么本次函数的返回值就是该值,举例:
    function fn3(){
      return [1,3,5]; 
      //数组是一个对象类型的值,
      //所以数组是一个复杂数据类型的值
      //-->本次构造函数的真正返回值就是该数组
      //-->不再是fn3构造函数的实例
    }
  var f3=new fn3();   //f3还是fn3的实例吗?错
  //f3值为[1,3,5]

三、对象的增删改查

js 复制代码
var obj = {name: "Tom", age: 18};
obj.height = "180cm";  // 设置对象的属性
delete obj.age;  // 删除对象的属性
obj.name = "Jerry";  // 修改对象的属性
console.log(obj);  // {name:"Jerry", height: "180cm"}

1.获取/设置对象的属性

js 复制代码
// 1、 对象.属性名
console.log(hero.name);
// 2、 对象['属性名']--推荐使用
console.log(hero['name']);

// 设置属性
hero.gender = "男"; // 添加一个不存在的属性
hero["gender"] = "male"; // 修改一个已存在的属性值

2.访问对象的方法

js 复制代码
// 对象.方法名
hero.attack( );

3.遍历对象的方法

js 复制代码
// 1. for in
语法: for (var 变量名 in 对象){} 变量名 = 对象的属性名
对象中有几个属性,循环体就会执行几次

var obj = { name:'孙悟空',  age:30,  gender:'boy', 
  skill:function () { alert('筋斗云'); } }
for (var key in obj) {
  console.log(key + '------' + obj[key]);	
}

四、this关键词

1.函数中的this指向

js 复制代码
function fn() {
  console.log(this);
}
fn();  //Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, ...}

2.对象方法中的this指向

js 复制代码
对象的方法中:this 指向 调用该方法的当前对象
var obj = {
  name: 'zs',
  fn: function() {
    console.log(this.name);
  }
}
obj.fn(); // zs

3.构造函数中的this

js 复制代码
在构造函数中:this 就是构造函数创建的对象

function Fn(){
  this.name = 'zs';
  this.age = 18;
  console.log(this);    // Fn {name: "zs", age: 18}
}
var obj = new Fn();

五、内存泄露

js 复制代码
var p1={age:100,gender:"女",say:function(){}}
var p2={age:100,gender:"女",say:function(){}}
var p3={age:100,gender:"女",say:function(){}}
var p4={age:100,gender:"女",say:function(){}}
var p5={age:100,gender:"女",say:function(){}}
var p6={age:100,gender:"女",say:function(){}}

//上述代码,
//a、存在很多冗余代码 
//b、所有的人对象都有say方法,并且功能相似,但是他们占据了不同的内存-->会导致内存浪费(内存泄漏)

六、构造函数

js 复制代码
function Person(age,gender){
  this.age=age;
  this.gender=gender;
  this.say=function(){ ... }  //此时的内存依然浪费了-->原型
}

var p1=new Person(5,"未知"); //使用这种方式创建对象,代码整洁了很多
    
var p2=new Person(5,"未知"); //Person是p1的构造函数,p2是Person构造函数的实例
var p3=new Person(5,"未知");
var p4=new Person(5,"未知");
var p5=new Person(5,"未知");
var p6=new Person(5,"未知");
    
// 任何函数都可以当成构造函数 例: function CreateFunc(){ }
// 只要把一个函数通过new的方式来进行调用,我们就把这一次函数的调用方式称之为:构造函数的调用
// new CreateFunc(); 此时CreateFunc就是一个构造函数
// CreateFunc();     此时的CreateFunc并不是构造函数    
// 其它见上面创建对象的方式 - 自定义构造函数

七、js中继承的概念

js 复制代码
function Person(name,age){
  this.name=name;
  this.age=age;
  this.say=function(){}
}
var p1=new Person();
var p2=new Person();
    
//p1对象和p2对象的say方法是否是同一个方法:false
console.log(p1.say===p2.say); 
js 复制代码
// 由于say方法可能功能相似,但是不是同一个方法(没有指向同一块内存,会造成内存浪费)
// 解决方案:把say方法写在他们共同的(父对象)中
// 其实他们共同的父对象,就可以通过:Person.prototype来获取

//只要把say方法写在Person.prototype中,那么say方法就是同一个方法
Person.prototype.run=function(){ console.log('时速500KM');}
p1.run(); // 此时p1和p2都可以访问到run方法
p2.run();
// 验证p1.run和p2.run是否是同一个方法?
console.log(p1.run == p2.run); //指向同一个方法,这种方法避免了内存的浪费
console.log(p1.run == Person.prototype.run); // true
    
var p3=new Person();
console.log(p3.run == p1.run); //true
console.log(p3.run === p1.run);//true
// 结论:只要往某个构造函数的prototype对象中添加某个属性、方法,那么这样的属性、方法都可以被所有的构造函数的实例所共享
// 这里的【构造函数的prototype对象】称之为原型对象
// Person.prototype是 p1 p2 p3 的原型对象
// Person.prototype是Person构造函数的【实例】的原型对象

// 猜猜看?
//  Person的原型对象是谁呢?
//  -->首先要知道Person的构造函数:-->Function
//  -->所以Person的原型对象是:Function.prototype

//  p1的原型对象是谁呢?
//  -->首先要知道p1是谁创建的?    -->Person
//  -->所以p1的原型对象时:     Person.prototype

继承的实现方式

js 复制代码
// 1. 原型链继承
function Dog(){} // 1.1 创建一个构造函数
var d1=new Dog(); // 1.2 通过new 构造函数得到 d1 实例
// d1.say=function(){}  // 不行:错误写法
Dog.prototype.say=function(){ console.log('汪汪汪');} //正确写法:为了让d1有一个叫的方法

// 2. 原型链继承2
// a、一般情况下,先改变原型对象,再创建对象
// b、对于新原型,添加一个 constructor属性,从而不破坏原对象原型的结构
Person.prototype = {
  constructor: Person,  
  say:function(){},
  run:function(){}
}

// 3. 拷贝继承(混入继承)
 var o3={gender:"男",grade:"初三",group:"第五组",name:"张三"};
var o4={};
//a、取出o3对象中的每一个属性
for (var key in o3) {  //key就是o3对象中的每一个属性     
  var value = o3[key]; //b、获取到对应的属性值
  o4[key] = value; //c、把属性值放到o4中
}
o4.name="李四"  // 修改克隆对象,把该对象的name属性改为"李四",就不会影响到o3
console.log(o4);    // 最终的目标对象的结果
//结论:后续如果修改了o4对象中的相关属性,就不会影响到o3
相关推荐
一个专注写代码的程序媛1 小时前
vue组件间通信
前端·javascript·vue.js
一笑code1 小时前
美团社招一面
前端·javascript·vue.js
懒懒是个程序员2 小时前
layui时间范围
前端·javascript·layui
NoneCoder2 小时前
HTML响应式网页设计与跨平台适配
前端·html
凯哥19702 小时前
在 Uni-app 做的后台中使用 Howler.js 实现强大的音频播放功能
前端
烛阴2 小时前
面试必考!一招教你区分JavaScript静态函数和普通函数,快收藏!
前端·javascript
GetcharZp2 小时前
xterm.js 终端神器到底有多强?用了才知道!
前端·后端·go
JiangJiang2 小时前
🚀 React 弹窗还能这样写?手撸一个高质量 Modal 玩起来!
前端·javascript·react.js
吃炸鸡的前端2 小时前
el-transfer穿梭框数据量过大的解决方案
前端·javascript
高德开放平台2 小时前
文末有奖|高德MCP 2.0 出行领域首发打通大模型与高德地图APP互联
前端