1、fuction和Object原型链
- 总结:先有Object.prototype(原型链顶端),Function.prototype继承Object.prototype而产生,最后,Function和Object和其它构造函数继承Function.prototype而产生。
// 创建了一个能返回两个参数和的函数
const adder = new Function("a", "b", "return a + b");
// 调用函数
adder(2, 6);
2、JS中一切函数都是Function构造函数创造的吗?
2、使用new关键字实例化的时候发生了什么?
3、JS 手撕new:
- 1.创建空对象
- 2.this指向新对象,执行构造函数的代码
- 3.设置原型链,新对象的__proto__指向构造函数的prototype对象
- 4.判断:如果传入对象的类型是一个对象,返回新对象;反之,直接返回
/**
*
1、创建一个空对象
2、this指向新对象,执行构造函数的代码
3、设置原型链,新对象的_proto_指向构造函数的prototype对象
4、判断:如果传入对象的类型是一个对象,返回新对象;反之,直接返回
*/
function myNew(){
debugger
var obj = new Object();
var Constructor = [].shift.call(arguments)
var result = Constructor.apply(obj,arguments)
obj._proto_ = Constructor.prototype;
return typeof result === 'object' ? result:obj
}
function F(){
console.log('F----')
}
let f = myNew(F)
console.log(f)
3、隐式原型属性_proto_
function A() {}
A.prototype.n = 1
//隐式原型属性
var b = new A();
A.prototype = {
n: 2,
m: 3
}
var c = new A();
console.log(b.n, b.m, c.n, c.m)
4、构造函数 constructor
let f = new Funtion('x', 'return x')
class _Function {
constructor (param, expression) {
this.param = param
this.expression = expression
}
}
let _f = new _Function('x', 'return x')
console.log(_Function.prototype) // _Function {}
console.log(_Function.prototype.prototype) // undefined
console.log(_Function.prototype.__proto__) // {}
console.log(Function.prototype) // [Function]
console.log(Function.prototype.prototype) // undefined
console.log(Function.prototype.__proto__) // {}
4.1、构造函数写法
// 定义构造函数
// 这里遵循一个常见的编程约定:从某种意义上讲,定义构造函数既是定义类,并且类名首字母要大写。
function People(name, age) {
this.name = name;
this.age = age;
};
People.prototype.showName = function () {
console.log(this.name);
};
// 使用构造函数
var p1 = new People('wqh', 18);
p1.showName();
var p2 = new People('w', 19);
var p3 = new People('q', 20);
console.log(p1, p2, p3);
- new出的不同实例的_ _ proto _ _都指向了同一个原型。
- 原型上的constructor都指向了同一个构造函数People。
- People构造函数prototype原型上写的方法,被实例对象‘继承’了。
- 只有写在prototype原型上的属性才会被‘继承’(共有属性),其它地方是私有属性
4.2、prototype被重写
function People(name, age) {
this.name = name;
this.age = age;
};
People.prototype = {
showName: function () {
console.log(this.name);
}
}
// 使用构造函数
var p1 = new People('wqh', 18);
p1.showName();
var p2 = new People('w', 19);
var p3 = new People('q', 20);
console.log(p1, p2, p3);
- 当prototype重定义为一个对象时,这个新定义的原型对象不含有constructor属性,因此类的实例也不含有constructor属性。
function People(name, age) {
this.name = name;
this.age = age;
};
People.prototype.showName = function () {
console.log(this.name);
};
// 使用构造函数
var p1 = new People('wqh', 18);
// p1.prototype.say = function () {
// console.log(this);
// }; // undefined
p1.say = function () {
debugger
console.log(this);// undefined
};
4.3、prototype被重写的解决方案
function People(name, age) {
this.name = name;
this.age = age;
};
People.prototype = {
constructor: People,
showName: function () {
console.log(this.name);
}
}
// 使用构造函数
var p1 = new People('wqh', 18);
p1.showName();
var p2 = new People('w', 19);
var p3 = new People('q', 20);
console.log(p1, p2, p3);
- 显式给原型添加一个构造函数
5、class
5.1 class写法
class People {
constructor (name, age) {
this.name = name;
this.age = age;
}
showName () {
console.log(this.name);
}
};
// 使用构造函数
var p1 = new People('wqh', 18);
p1.showName();
var p2 = new People('w', 19);
var p3 = new People('q', 20);
console.log(p1, p2, p3);
class People {
constructor() {
// ...
}
showName() {
// ...
}
}
// 等同于
People.prototype = {
constructor() {},
showName() {},
};
6、原型prototype
- 每个函数都有一个prototype属性,一般情况下,fn.prototype都是对象,但有个特例Function.prototype
7、隐式原型链_proto_
var F = function(){}
Object.prototype.a =function(){}
Function.prototype.b =function(){}
var f = new F()
8、Function构造函数 vs 函数声明 vs函数表达式
- Function构造函数
var multiply = new Function('x', 'y', 'return x * y');
- 函数声明
function multiply(x, y) {
return x * y;
} // 没有分号
- 函数表达式
var multiply = function(x, y) {
return x * y;
};
9、函数属性和方法
- 因为函数是javascript中的特殊对象,所以它们也可以拥有属性和方法。
9.1. length属性
- 函数的length属性是只读属性,他代表函数实参的数量。
9.2. prototype属性
- 每一个函数都包含一个prototype属性,这个属性是指向一个对象的引用,这个对象叫‘原型对象’(prototype object)。
- 每一个函数都包含不同的原型对象。
- 当将函数用作构造函数的时候,新创建的对象会从原型对象上继承属性。
9.3. call()方法和apply方法()
9.4. bind()方法
9.4. toString()方法
- 方法返回一个字符串,这个字符串和函数声明语句的语法有关,大多数(非全部)的toString()方法的实现都返回函数的完整源码。