[渡一] 171111 原型链、方法重写、call&apply

本文详细介绍了JavaScript中的原型链概念,包括如何改变默认原型对象,原型链的顶端是Object.prototype。接着讨论了原型方法的重写,解释了中间目标覆盖上游目标的原理,并通过例子说明了如何使用call避免重写带来的影响。最后,阐述了call和apply方法的使用,它们可以改变函数体内this的指向,调整作用域,并对比了两者接收参数的不同方式。

tips1.原型链

//一个原型(本身是一个对象)中有两个属性:constructor & __proto__
GrandFather.prototype.lastName = 'deng';

function GrandFather() {
    this.bike = 1;
}
Father.prototype = new GrandFather();

function Father() {
    this.fortune = {
        money: 9999999,
        house: 4 
}
    this.name = "hahah"
    this.girl = 'h1' 
}
Son.prototype = new Father(); //更改了原型

function Son() {
    this.name = 'heihei'
    this.age = 20;
}

var oSon = new Son();
oSon.lastName = 'Chen'; 

// GrandFather.prototype.lastName = 'hong';
var oSon2 = new Son();
console.log(oSon2.lastName);

oSon.__proto__.fortune.house += 1; 
//  Son.prototype.fortune.house += 1;
// Son.prototype.fortune.house += 1;
var oSon2 = new Son();
console.log(oSon2.fortune.house);
console.log(oSon.fortune.money);
oSon.girl = 'h2';
console.log(oSon.girl);
console.log(oSon2.girl);
// oSon.lastName = {
//     name: 'chen'
// }
console.log(oSon.lastName);
console.log(oSon2.lastName);
oSon.fortune = {
    money: 8888888,
    house: 3
} 
// oSon.__proto__.fortune
// Son.prototype.fortune = {
//         money: 8888888,
//         house: 3
//}

// Son.prototype = {
//     name: 'hehe',
//     fortune: {
//         money: 7777777,
//         house: 2
//     }
// }  
var oSon3 = new Son();
console.log(oSon.fortune.house); //3
console.log(oSon3.fortune.house); //5
console.log(oSon2.fortune.house); //5

这里写图片描述

  • 改变默认原型对象
  • oSon.lastname = ‘cherry’ | Oson.fortune = { house = 3} 这些是在oSon对象里添加了新的属性,该行为只与自身有关
  • oSon.fortune.house = ‘4’ 是改变了原型的某一项属性,凡是指向该原型对象,均受影响
  • Son.prototype = {fortune: { house: 2 }} 是更改了原型的指向,在更改前的对象的_proto_指向不变,新建的对象会按照新的原型继承
  • 原型链的顶端都是Object.prototype -> {} | var obj = Object.create(demo) [括号里传参数null(没有原型)或者object(指定原型)] / [obj._proto_== demo]

tips2.原型方法的重写

GrandFather.prototype.lastName = 'deng';
GrandFather.prototype.say = function() {
    console.log('tell me GrandFather');
};

function GrandFather() {
    this.bike = 1;
}
Father.prototype = new GrandFather();

function Father() {
    this.fortune = {
        money: 9999999,
        house: 4 
    }
    this.name = "hahah"
    this.girl = 'h1'
    this.say = function() {
        console.log('tell me father');
    }
}
Son.prototype = new Father(); 

function Son() {
    this.name = 'heihei'
    this.age = 20;
}

var oSon = new Son();
oSon.say();
  • 对象通过原型链从下游向上游寻找目标,若顶端有目标,中间有目标,则使用中间的目标,中间的目标覆盖上游目标。
Object.prototype.toString(); 
//谁调用了这个方法,调用方法的类型就可以输出
var obj = {};
obj.toString(); //[object Object]
var arr = [1, 2, 3];
arr.toString(); //1,2,3  用toString没有实现功能
//arr.constructor(查询构造函数) -> function Array(){[native code]}
//Array.prototype -> toString  方法在下游被重写
  • 原本在原型链顶端的Object.prototype中有目标方法toString();但在搜索过程中下游Array.prototype中重新定义了toString();导致无法实现预想功能
console.log(Object.prototype.toString.call(arr));
  • 使用call来改变this的指向,即‘arr’使用‘Object.prototype.toString’方法而不是默认的‘Array.prototype.toString’

tips3.call&apply

  • 每个函数都包含两个非继承而来的方法:call()方法和apply()方法。

  • 都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。

  • 一般来说,this总是指向调用某个方法的对象,但是使用call()和apply()方法时,就会改变this的指向。

  • 相同点:这两个方法的作用是一样的。

  • 不同点:接收参数的方式不同。

  • apply()方法 接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。

    语法:apply([thisObj [,argArray] ]);,调用一个对象的一个方法,2另一个对象替换当前对象。 
    说明:如果argArray不是一个有效数组或不是arguments对象,那么将导致一个 TypeError,如果没有提供argArray和thisObj任何一个参数,那么Global对象将用作thisObj。

  • call()方法 第一个参数和apply()方法的一样,但是传递给函数的参数必须列举出来。

    语法:call([thisObject[,arg1 [,arg2 [,…,argn]]]]);,应用某一对象的一个方法,用另一个对象替换当前对象。

    说明: call方法可以用来代替另一个对象调用一个方法,call方法可以将一个函数的对象上下文从初始的上下文改变为thisObj指定的新对象,如果没有提供thisObj参数,那么Global对象被用于thisObj。

  • 后面使用前面的功能,后面替换前面的对象

function Person(name, age) {
    //(Person)var this = {
    //name:null,
    //age:null,                       --------------??
    //}
    this.name = name;
    this.age = age;
}

function Student(name, age, myClass) {
    //构造函数,(Student)var this = {
    //myClass:null,
    //name:
    //age:
    //}
    Person.call(this, name, age); //Person.name -> Student.name
    this.myClass = myClass;

}
console.log(new Student('cst', 20, 1));
  • (student)替换了(person)的this,相当于student使用了person的方法
var numObj = {
          x: 1,
          y: 2
}

function add(a, b) {
    console.log(this.x + a + this.y + b);
}
add(3, 4); //NaN  undefined+3+undefined+4
//window.add.call(window) this->window  window里没有x,y
// add.call(numObj, 3, 4); //10
add.apply(numObj, [3, 4]);
  • numObj使用了add中的方法,numObj把自己的属性代入进去
function cat() {}
     cat.prototype = {
         food: "fish",
         say: function() {
             alert("I love " + this.food);
         }
     }
 var blackCat = new cat;
 blackCat.say();
 var whiteDog = {
     food: 'bone',
 }
blackCat.say.call(whiteDog);
//动态改变this,当一个对象没有某个方法,但是其他的有
  • whiteDog使用blackCat的方法,并带着自己的参数‘bone’
window.color = 'red';
document.color = 'yellow';

var s1 = {
    color: 'blue'
};

function changeColor() {
    console.log(this.color);
}

changeColor.call(); //red (默认传递参数)
changeColor.call(window); //red
changeColor.call(document); //yellow
changeColor.call(this); //red      -------------------??
changeColor.call(s1); //blue
var Pet = {
    words: '...',
    speak: function(say) {
        console.log(say + this.words)
    }
}
Pet.speak('Speak'); // 结果:Speak...

var Dog = {
    words: 'Wang'
}

//将this的指向改变成了Dog
Pet.speak.call(Dog, 'Speak'); //结果: SpeakWang
  • Dog使用Pet的方法

[1127追加]: 
tip1:探索普通函数和构造函数内部区别

function test() {
    console.log(this);
    console.log('test');
}
test();
//'this'window.this  即函数内部没有创建this对象
//普通函数执行功能

这里写图片描述

function Test() {
//var this = {__proto__:test.prototype}
console.log(this);
console.log('test');
//return this
}
var a = new Test();

//通过new定义函数,是构造函数,通常每个单词首字母大写
//通过new来执行函数,会在函数中默认定义一个this对象,会返回一个对象
//运行结果可以看出'this'并没有输出,是函数内部的this对象

这里写图片描述

function test() {
console.log(this);
console.log('test');
}
test();
test.call(window);

var obj = {
name: 'cst'
}
test.call(obj);


//执行test 相当于test.call(window)  'window' call 'test' 
//括号内第一个参数就决定了前面这个函数中this是谁
//不传参数默认为test.call(window)
//传入参数'obj'  'obj' call 'test' =>(this->obj)=>console.log(obj)

这里写图片描述

function Person(name, age, sex) {
//预编译阶段构造函数 creative new this {}
//预编译后产生this对象,每次执行都新建一个对象,都不是一个this
    this.name = name;
    this.age = age;
    this.sex = sex;
}
var oPerson = new Person(); 
//构造函数的方式运行函数,会创建this对象,执行时this才有意义
function Student(name, age, sex, grade, clas) {
// creative this {} 

// this.name = name;
// this.age = age;
// this.sex = sex;
Person.call(this, name, age, sex); //不传参数默认是window  在此处传实参
this.grade = grade;
this.clas = clas;
//return this;
}
var oStudent = new Student('yp', 18, 'man', 3, 3);



06-22
### 得物技术栈及开发者文档分析 得物作为一家专注于潮流商品的电商平台,其技术栈和开发者文档主要围绕电商平台的核心需求展开。以下是对得物技术栈及相关开发资源的详细解析: #### 1. 技术栈概述 得物的技术栈通常会涵盖前端、后端、移动应用开发以及大数据处理等多个领域。以下是可能涉及的主要技术栈[^3]: - **前端开发**: 前端技术栈可能包括现代框架如 React 或 Vue.js,用于构建高效、响应式的用户界面。此外,还会使用 Webpack 等工具进行模块化打包和优化。 - **后端开发**: 后端技术栈可能采用 Java Spring Boot 或 Node.js,以支持高并发和分布式架构。数据库方面,MySQL 和 Redis 是常见的选择,分别用于关系型数据存储和缓存管理。 - **移动应用开发**: 得物的移动应用开发可能基于原生技术(如 Swift/Kotlin)或跨平台框架(如 Flutter)。这有助于确保移动端应用的性能和用户体验一致性。 - **大数据云计算**: 在大数据处理方面,得物可能会使用 Hadoop 或 Spark 进行数据挖掘和分析。同时,依托云服务提供商(如阿里云或腾讯云),实现弹性扩展和资源优化。 #### 2. 开发者文档分析 类似于引用中提到的 Adobe 开发者文档模板[^2],得物也可能提供一套完整的开发者文档体系,以支持内部团队协作和外部开发者接入。以下是开发者文档可能包含的内容: - **API 文档**: 提供 RESTful API 或 GraphQL 的详细说明,帮助开发者快速集成得物的功能模块,例如商品搜索、订单管理等。 - **SDK 集成指南**: 针对不同平台(如 iOS、Android 或 Web)提供 SDK 下载和集成教程,简化第三方应用的开发流程。 - **技术博客**: 分享得物在技术实践中的经验成果,例如如何优化图片加载速度、提升应用性能等。 - **开源项目**: 得物可能将部分技术成果开源,供社区开发者学习和贡献。这不仅有助于提升品牌形象,还能吸引更多优秀人才加入。 #### 3. 示例代码 以下是一个简单的示例代码,展示如何通过 RESTful API 调用得物的商品搜索功能(假设接口已存在): ```python import requests def search_items(keyword, page=1): url = "https://api.dewu.com/v1/items/search" headers = { "Authorization": "Bearer YOUR_ACCESS_TOKEN", "Content-Type": "application/json" } params = { "keyword": keyword, "page": page, "size": 10 } response = requests.get(url, headers=headers, params=params) if response.status_code == 200: return response.json() else: return {"error": "Failed to fetch data"} # 调用示例 result = search_items("Air Jordan", page=1) print(result) ``` 此代码片段展示了如何通过 Python 请求得物的 API,并获取指定关键词的商品列表。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值