来到人世间,一定要看一看太阳
微信图片_20210713234614.jpg
原型链
创建对象有几种方法
字面量方式
const obj = {
属性名: 属性值,
方法名: function() {}
}
内置的构造函数创建对象
像Object,Function,Array,Date,String Number,Boolean
工厂模式创建对象
function createBook(name, author) {
let o = new Object()
o.name = name
o.author = author
o.logDes = function() {
console.log('作者是:' + this.author)
}
return o
}
const book1 = new createBook('语文', 'chris')
const book2 = new createBook('数学', 'curry')
自定义构造函数创建对象
-
具体步骤
a、提供一个构造函数
b、通过this指针来设置属性和方法
c、通过new操作符创建对象
-
实现细节
a、我们使用new关键字调用构造函数的时候,内部默认会创建一个空对象
b、默认会把这个空的对象赋值给this
c、通过this来设置新对象的属性和方法
d、在构造函数的最后,默认会把新创建的对象返回
自定义构造函数跟工厂函数对比
a、构造函数首字母大写
b、构造函数的创建方式内部会自动创建空对象并且赋值给this
c、默认会自动返回新创建的对象
<script>
//001 提供一个构造函数
//构造函数简单介绍:
//作用:对对象进行一些初始化的设置
//和普通函数区别:(01)首字母大写(02)调用方式不一样和new配合使用
function Person(name,age){
// 默认 创建对象
//var o = new Object();
//默认会赋值给this
//this = o;
// 002 通过this指针来设置属性和方法
this.name = name;
this.age = age;
this.showName = function(){
console.log(this.name);
};
this.showAge = function(){
console.log(this.age);
}
//默认返回
//return this;
}
//03 使用new操作符来创建对象
var p1 = new Person("张三",20);
var p2 = new Person("张老汉",200);
console.log(p1);
console.log(p2);
</script>
instanceof的原理
function Person(name, age) {
this.name = name
this.age = age
}
function Student(score) {
this.score = score
}
Student.prototype = new Person('kobe', 28)
const student = new Student(100)
console.log(student instanceof Student) // true
console.log(student instanceof Person); //true
console.log(student instanceof Object); //true
由上可知,student有一条属于自己的原型链,Student,Person,Object对象的原型属性所指向的原型对象都在这条原型链上。
检测对象A是不是另一个对象B的实例的原理是:查看对象B的prototype属性指向的原型对象是否在对象A的原型链上,若在则返回true,若不在则返回false。
类
类的声明
- 在JavaScript中,方法可以当做类来使用:首先定义一个方法,这如同一个类里面的属性使用this变量定义,方法通过prototype来定义
function Hello() {
this.hello = 'hello'
}
Hello.prototype.sayHello = function(name) {
console.log(this.hello + ' ' + name)
}
- class
生成实例?声明一个类,怎么生成类的实例
继承
call,apply,bind的共同点跟区别
-
相同点
都是用来绑定函数执行时this的指向(改变函数执行时的上下文),支持传参,调用它们的对象必须是一个函数Function
区别
// call
Function.call(obj, arg1, arg2, arg3, ...);
// apply,有两个参数,第二个是类数组
Function.apply(obj, [argArray]);
// bind,bind 方法的返回值是函数,需要手动调用才会执行,而 apply 和 call 则是立即调用
Function.bind(obj, arg1, arg2, arg3, ...);
const obj = {
name: '小鸭子',
};
function say (arg1, arg2) {
console.log(`${this.name ? `我是一只${this.name},` : ''}${arg1},${arg2}`);
}
say('咿呀咿呀哟', '呱呱!'); // 咿呀咿呀哟,呱呱!
say.call(obj, '咿呀咿呀哟', '呱呱!') // 我是一只小鸭子,咿呀咿呀哟,呱呱!
say.apply(obj, ['咿呀咿呀哟', '呱呱!']); // 我是一只小鸭子,咿呀咿呀哟,呱呱!
const manualSay = say.bind(obj, '咿呀咿呀哟', '呱呱!'); // 绑定但不是立即执行
manualSay(); // 手动执行,输出:我是一只小鸭子,咿呀咿呀哟,呱呱!
- call实现
// call 实现
Function.prototype.myCall = function(context) {
context = context || window; // 默认 window
const args = [...arguments].slice(1); // 参数
const fn = Symbol(); // 给 context 设置一个独一无二的属性,避免覆盖原有属性
context[fn] = this; // 这里的 this 指向调用它的函数 fn
const result = context[fn](...args); // 调用之
delete context[fn]; // 删除添加的属性
return result; // 返回值
}
say.myCall(obj, '咿呀咿呀哟', '呱呱!') // 我是一只小鸭子,咿呀咿呀哟,呱呱!
-
apply实现
// apply 实现 Function.prototype.myApply = function(context, args) { context = context || window; // 默认 window args = [...args]; // 参数 const fn = Symbol(); // 给 context 设置一个独一无二的属性,避免覆盖原有属性 context[fn] = this; // 这里的 this 指向调用它的函数fn const result = context[fn](...args); // 调用之 delete context[fn]; // 删除添加的属性 return result; // 返回值 } say.myApply(obj, ['咿呀咿呀哟', '呱呱!']) // 我是一只小鸭子,咿呀咿呀哟,呱呱!
- bind实现
// bind 实现
Function.prototype.myBind = function(context) {
context = context || window; // 默认 window
const args = [...arguments].slice(1); // 参数
const fn = this; // 这里的 this 指向调用它的函数 fn
return function () {
return fn.apply(context, args);
};
}
const manualSay = say.myBind(obj, '咿呀咿呀哟', '呱呱!');
manualSay(); // 手动执行,输出:我是一只小鸭子,咿呀咿呀哟,呱呱!
用javascript实现对象的继承/继承的几种方式,这几种方式的优缺点
https://www.jianshu.com/p/494c15106223