JavaScript面向对象
JavaScript 语言使用构造函数(constructor)做为对象的模板。所谓”构造函数”,就是专门用来生成实例对象的函数。它就是对象的模板,描述实例对象的基本结构。一个构造函数,能够生成多个实例对象,这些实例对象都有相同的结构javascript
function Person(name, age, sex) { 'use strict'; this.name = name; this.age = age; this.sex = sex; } Person() 报错 new Person("zhangxc", 29, "male");
一、new关键字 命令内部实现java
function _new(constructor, params) { // 接受个数不肯定参数,第一个参数:构造函数;第二个到第n个参数:构造函数传递的参数。 // 1. 首先将参数组成一个数组 // 首先 .slice 这个方法在不接受任何参数的时候会返回 this 自己,这是一个 Array.prototype 下的方法,所以 this 就是指向调用 .slice 方法的数组自己。 var args = Array.prototype.slice.call(arguments); // arguments伪数组,获取函数的全部参数的伪数组。 // 等价于 // [].slice.call(arguments); // 2. 获取构造函数 var constructor = args.shift(); // shift()返回数组第一个元素 // 3. 使用构造函数原型建立一个对象。咱们但愿以这个现有的对象做为模板,生成新的实例对象,这时就可使用Object.create()方法。 var context = Object.create(constructor.prototype); // Object.create()参数是一个对象,新建的对象继承参数对象的全部属性 // 4. 将参数属性附加到对象上面 var result = constructor.apply(context, args); // 5. 返回一个对象 return (typeof result === 'object' && result != null) ? result : context; } function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; } var args1 = _new(Person, "zhangxc", 18, "male"); // {name: "zhangxc", age: 18, sex: "male"} var args2 = new Person("zhangxc", 18, "male"); // {name: "zhangxc", age: 18, sex: "male"}
new.target属性git
若是当前函数是new命令调用,new.target指向当前函数(构造函数的名称),不然为undefined。github
function Test() { console.log(new.target === Test); } Test() // false new Test() // true
二、this关键字
this老是指向调用该方法的对象,在最外面调用就指向window
bind, call, apply均可以改变this的指向数组
var name = "window"; var obj = { name: "object" } function fun() { console.log(this.name); } 一、直接调用 fun() // window 由于此时fun() this指向window对象 二、fun.call(obj); // "object" call改变了this的指向,此时this指向obj对象,this.name 在obj对象里面取值,而不是window对象了。
详细讲解链接:https://github.com/mqyqingfen...app
三、对象的继承
JavaScript 语言的继承不经过 class,而是经过“原型对象”(prototype)实现。函数
prototype原型对象ui
JavaScript 继承机制的设计思想就是,原型对象的全部属性和方法,都能被实例对象共享。也就是说,若是属性和方法定义在原型上,那么全部实例对象就能共享,不只节省了内存,还体现了实例对象之间的联系。原型对象的做用,就是定义全部实例对象共享的属性和方法。这也是它被称为原型对象的缘由,而实例对象能够视做从原型对象衍生出来的子对象。this
// 定义水果构造函数 function Fruit(name, color) { this.name = name; this.color = color; } // 实例化apple对象 var apple = new Fruit("apple", "red"); // 实例化banana 对象 var banana = new Fruit("banana", "yellow"); // 若是他们有共同的属性和方法那么就使用 prototype // 修改 Fruit构造函数 Fruit.prototype.address = "china"; Fruit.prototype.eat = function() { console.log(this.name + "-----" + this.color); } apple.addess // china banana.address // china apple.eat() // apple ---- red banana.eat() // banana ---- yellow function M1() { this.hello = 'hello'; } function M2() { this.world = 'world'; } **// 一、继承M1,M2本身的属性和方法(hasOwnProperty)** function S() { M1.call(this); M2.call(this); } **// 二、继承M1原型链上的属性和方法** S.prototype = Object.create(M1.prototype); **// 三、继承M2原型链上的属性和方法** Object.assign(S.prototype, M2.prototype); // 指定构造函数 S.prototype.constructor = S; var s = new S(); s.hello // 'hello' s.world // 'world'
四、原型链
最透彻的原型链讲解 哈哈prototype
**1. 每个函数都有prototype属性指向他的原型对象** **2. 每个对象都有__proto__属性指向他的原型对象**
而后以Date()时间 构造函数为例讲解
证实:
var data = new Date(); 由于: data是一个实例对象因此他有__proto__属性指向他的原型对象 Date是一个构造函数因此他有prototype属性指向他的原型对象 因此:Date.prototype == data.__proto__ // Date{} true data.__proto__是一个对象 由于:javascript规定全部对象都有原型 因此: data.__proto__.__proto__ == Object.prototype // true 这就是原型链了 data.__proto__.__proto__ data对象继承了 Date Object 原型对象的属性和方法。