大纲:
构造函数
手写new命令
原型链
Object对象的相关方法
(x)易错点
- constructor表示构造函数和原型对象之间的关联关系,如果修改了protype属性,要同时修改constructor属性,防止引用出错
var P = function () {};
var p = new P();
var C = function () {};
C.prototype = p; -------- C.prototype修改成了p,所以c.constructor === p.constructor === P.prototype.constructor,
var c = new C();
c.constructor.prototype === p // false --------------- 要想是p,就需要指定c.constructor = C
c.constructro.prototype === P.prototype // true
(1) 实例只能访问构造函数prototype上的属性,不能直接修改构造函数的prototype属性
(2) 如果要修改,只能通过 x.constructor.prototype.color='yellow'方式修改
function A() {}
A.prototype.color = 'red'
const x = new A()
const y = new A()
x.color = 'yellow' ------------- 因为x.color是给x本身添加属性并赋值,而不是修改x的原型对象的属性
y.color????? // 'red'
- instanceof
1. instanceof原理:检查 ( 右边构造函数的prototype属性 ) 是否在 ( 左边对象的原型链上 )
2. instanceof失效的情况:
- 如果一个对象的__proto__是null,instanceof就会判断失效
- Object.prototype.__prototo__ === null
- Object.prototype instanceof Ojbect // false
// Object.create(null) instanceof Object // false,因为创建的实例没有任何属性和方法,也没有原型
(1)构造函数
- 函数名大写,this代表将要生成的实例,使用new命令生成实例
- new命令:执行构造函数,返回实例对象(new命令本身就可以执行构造函数,所以后面的括号可以不要)
- 如何保证构造函数和new命令一起使用?(忘记使用new了)
- 在构造函数内部使用严格模式:use strict,在严格模式下this不能指向window,默认是undefined,undefined不能添加属性,就会报错
- 在构造函数内部判断是否使用了new命令
- new命令的原理?
- 生成一个空对象(作为要返回的实例对象)
- 将空对象的隐式原型指向构造函数的prototype属性
- 将构造函数中的this指向新生成的空对象
- 执行构造函数
-
手写new命令
前置知识:
1. new命令返回值
- new命令总是返回一个对象,要么是( 实列对象 ),要么return后面所跟的 (对象)
2. 构造函数中的return语句,使用new命令时的返回情况
- return 一个原始类型的值,使用new命令返回的是:-------------------------- this对象
- return 一个对象,使用new命令返回的是:--------------------------------- return后面紧跟的那个对象,而不是this对象
- 如果构造函数中没有return语句,则默认返回的是:-------------------------- this对象
3. 如何判断一个数据的数据类型?
- typeof:返回 number,string,boolean,undefined,symbol,ojbect,function(七种)
- instanceof:- 原理是检测 ( 右边构造函数的显示原型prototype )是否在左边 ( 实列对象的原型链上 )
- instanceof只能用于对象,不能用于原始类型的值
- Object.prototype.toString().call(参数) ----------- 返回"[object 类型]"
- js中的数据类型 number, string, boolean, null, undefined, symbol, object (七种)
4. arguments对象
- 返回实参组成的类似数组的对象,该对象具有length属性
5. 如何把arguments对象转换成真正的数组
- Array.from(arguments)
- Array.prototype.slice.call(arguments)
6. new命令的原理
- 新建一个空对象,作为要返回的实列对象
- 将空对象的隐式原型__proto__指向构造函数的显示原型prototype
- 将构造函数中的this指向空对象
- 执行构造函数
7. 如何新建一个对象
- Object.create(b) : 以参数对象为原型,生成实列对象
- new Object()
- 对象字面量
- 注意:const a = Object.create(b) 即可以实现 a.__proto__ === b == 构造函数.prototype
8. push unshift 和 pop shift
- push unsift 向数组添加数据,改变原数组,有参数,返回值是添加过后的数组长度 ( 不是返回添加的值,因为参数中已经知道 )
- pop shift 删除数据,改变原数组,没有参数,所以返回值是删除的数据值
9. new命令实行后的效果:
- 生成的对象可以访问构造函数的属性
- 生成的对象可以访问构造函数prototype上的属性
10. 手写new命令
function Constructor(name, age) {
this.name = name
this.age = age
// 构造函数如果执行new命令,默认返回的是this对象
// 这里模拟的是new命令,所以手动返回this对象
// 如果返回其他对象,不是this对象,需要在构造函数返回值中做判断
return this
}
Constructor.prototype.address = function() {
console.log('shanghai')
}
function _new() {
const obj = new Object()
// 等于 const obj = {}
// 等于 const obj = Object.create(null) ------- 以null为原型,生成实例对象
const paramsConstructor = Array.prototype.shift.call(arguments)
// 等于 [].prototype.shift.call(arguments)
// 等于 Array.prototype.shift.apply(arguments)
// shift 删除数组的第一个参数,改变原数组,返回被删除的值 ---------- push, unshift 返回被添加删除的值
// unshift 在数组的最前面添加数据,返回添加过后数组的长度 ---------- pop, shift 返回更新后的数组长度
// 把arguments对象中的构造函数参数取出
obj.__proto__ = paramsConstructor.prototype
// 将空对象的隐式原型指向构造函数的显示原型
const res = paramsConstructor.apply(obj, arguments)
// 将构造函数中的this指向空对象
// 空对象就能访问构造函数中的属性
// apply第二个参数是数组,但是类似数组的对象也可以,会转化成数组
return /Object/.test(Object.prototype.toString.call(res)) ? res : obj
// 如果构造函数的返回的是一个和this无关对象则返回该对象,即res(this对象也返回)
// 如果返回不是对象,就返回this对象,即空对象ojb
}
const b = _new(Constructor, 'wu', 10)
console.log(b)
1.https://github.com/mqyqingfeng/Blog/issues/13
-
new命令可以用Object.setPrototypeOf()方法来模拟
function A() {
this.name = 'wang'
}
const a = new A()
----
const resa = Object.setPrototypeOf({}, A.prototype) --------------- 将A.prototype设置成空对象的原型对象
A.call(resa) ------------------------------------------------------ 将构造函数中的this指向空对象,并执行构造函数
(2) 原型链
- 原型对象的作用: 定义所有实列对象所共享的属性和方法
- 所有对象都是 Objecr.prototype 的实例,所有对象都有toString和valueOf方法,因为都继承了Object.prototype上的这两个方法
-
Object.prototype.__proto__ === null
null没有任何属性和方法,也没有自己的原型,原型链到此中止 - constructor属性定义在prototype上,所以construstor能被所有实例对象所共享
即a.constructor === A.prototype.constructor = A
- constructor属性的作用
constructor的作用就是得知:实例对象到底是由哪个构造函数产生的
- 有了constructor属性,就可以从一个实例新建另一个实例
特殊的原型链
特殊的原型链:
结论:
(1) 所有 ( 函数对象 ) 都是 ( Function构造函数 ) 的实例
- 所以 Function.__proto__ === Function.prototype
- 所以 fn.__protot__ === Function.prototype
- 所以 Function instanceof Function // true
(2) 所有函数的prototype对象都是Obect构造函数的实例(!但是Object除外)
- Function.prototype instanceof Object // true
- function.prototype.__proto__ === Object.prototype
- Object.protype instanceof Object // false
(3)
Function instanceof Function ------------------- true
Function instanceof Object ------------------- true
Object instanceof Object ------------------- true
Object instanceof Function ------------------- true


(3)Object对象的相关方法
1. Object.getPrototypeOf
Object.getPrototypeOf()返回参数对象的原型对象,是获取原型对象的标准方法
Object.getPrototypeOf(params) 返回参数对象的原型对象,是获取原型对象的标准方法
function A() {}
const a = new A()
const res = Object.getPrototypeOf(a)
console.log(a.__proto__ === res) // true
console.log(A.prototype === res) // true
2. Object.setPrototypeOf(origin, pro)
将第二个参数设置成第一个参数的原型,返回该参数对象即第一个对象
Object.setPrototype(a,b) 将b对象设置成a对象的原型对象,返回值是a对象
const a = {}
const b = {name: 'wang'}
const res = Object.setPrototypeOf(a, b)
console.log(res) // {}
console.log(Object.getPrototypeOf(a)) // {name: 'wang'}
Object.setPrototypeOf(a, b)可以用来模拟new命令
function A() {
this.name = 'wang'
}
const a = new A()
----
const resa = Object.setPrototypeOf({}, A.prototype) --------------- 将A.prototype设置成空对象的原型对象
A.call(resa) ------------------------------------------------------ 将构造函数中的this指向空对象,并执行构造函数
3. Object.create()
Object.create()以参数对象为原型,返回实例对象
以下生成对象的方式等价
Object.create({})
Object.create(Object.prototype)
new Object()
如果想要生成不继承任何属性的对象,可以用如下写法
var obj = Object.create(null)
obj.valueOf()
// TypeError: Object [object Object] has no method 'valueOf'
因为obj的原型是null,所以obj不具备 Object.prototype上挂在的属性和方法,比如 valueOf,toString
Object.create()参数必须是个对象,不能为空或者不是对象
4. Object.prototype.isPrototypeOf
实例对象的isPrototypeOf用来判断该对象是否为参数对象的原型
var o1 = {};
var o2 = Object.create(o1); // o1是o2的原型对象
var o3 = Object.create(o2); // o2是o3的原型对象
o2.isPrototypeOf(o3) // true ---------------------- 实例对象的isPrototypeOf用来判断该实例对象是否是参数对象的原型
o1.isPrototypeOf(o3) // true
网友评论