Javascript重温OOP之类与对象

对象

对象的寄义

所谓对象,就是一种无序的数据鸠合,由若干个“键值对”(key-value)组成。

对象的建立

  1. 运用new运算符建立Object

    var p = new Object();
    p.name = "Tony";    
  2. 运用对象字面量的情势

    //对象字面量情势
    var p ={
        name: "tony",
        work: function(){
            console.log("working....");
        },
        _age: 18,
        get age(){
            return this._age;
        },
        set age(val){
            if( val <0 || val > 150){
                throw new Error("invalid value");
            }else{
                this._age = val;
            }
        }
    }
    console.log(p.name);

对象的基础操纵

  1. 成员属性的增加

    // Object.defineProperty()要领
    Object.defineProperty(p, "age",{value: 18, writable: false});
    //Object.defineProperties()要领 增加多个属性
    Object.defineProperties(p, {
        salary:{
            value: 1000,
            writable: false
        },
        gender:{
            value: true
        }
    });
  2. 成员的遍历

    • 运用 for..in语句

    • Object.keys()要领 返回一个包括对象键名的字符串数组

      var o ={};
      o.name = "jack";
      o.age = 20;
      for(var i in o){
          console.log(o[i]);
      } // jack, 20
      Object.keys(o); // ["name", "age"]
  3. 搜检对象是不是有某个属性

    • in 操纵符

    • Object.hasOwnProperty()要领

      var o = {name: "mariya"}
      "name" in o; // true
      o.hasOwnProperty("name"); // true
  4. 获得对象的属性特征形貌

    • Object.getOwnPropertyDescriptor(obj,property)

    Object.getOwnPropertyDescriptor(o, "name");
    //Object {value: "mariya", writable: true, enumerable: true, configurable: true}
  5. 删除属性

    • delete运算符,但有些对象的属性是删除不了的

    delete o.name; //true
    o.name;  // undefined 

成员特征

  • configurable 是不是可设置

  • writable 是不是可修正

  • enumerable 是不是可罗列

  • value属性的值

var person ={};
Object.defineProperties(person,{
    title: {value: 'fe',enumerable: true},
    age: {value: 19, enumerable: true, writable: true}
});
Object.getOwnPropertyDescriptor(person,'title');
// Object {value: "fe", writable: false, enumerable: true, configurable: false}
Object.getOwnPropertyDescriptor(person,'age');
// Object {value: 19, writable: true, enumerable: true, configurable: false}

Constructor属性

constructor一直指向建立当前对象的组织函数。

var arr = [];
console.log(arr.constructor === Array); // true
var Foo = function() {};
console.log(Foo.constructor === Function); // true
// 由组织函数实例化一个obj对象
var obj = new Foo();
console.log(obj.constructor === Foo); // true
console.log(obj.constructor.constructor === Function); // true

每一个函数都有一个默许的属性prototype,而这个prototypeconstructor默许指向这个函数。

function Person(name) {
    this.name = name;
};
Person.prototype.getName = function() {
    return this.name;
};
var p = new Person("jack");
console.log(p.constructor === Person);  // true
console.log(Person.prototype.constructor === Person); // true
console.log(p.constructor.prototype.constructor === Person); // true

类的建立

虽然js是门基于对象的言语,然则没有类这一观点的,虽然保留了class的关键字,但在ES6之前是没法运用的。所以,能够用组织函数模仿类的建立,也就是伪类。

所谓”组织函数”,实在就是一个平常函数,然则内部运用了this变量。对组织函数运用new运算符,就能够天生实例,而且this变量会绑定在实例对象上。

每一个组织函数都有一个prototype属性,指向另一个对象。这个对象的一切属性和要领,都会被组织函数的实例继续。

这意味着,我们能够把那些稳定的属性和要领,直接定义在prototype对象上。

//组织函数形式
function Person(age, name){ //Class
    this.age = age;
    this.name = name;
}
//将大众的属性或要领放在prototype属性上
Person.prototype.headCount = 1;
//建立实例对象
var p = new Person(19, 'johnsom');
var p1 = new Person(20, 'allen');

this

this示意当前对象,假如在全局作用范围内运用this,则指代当前页面对象window; 假如在函数中运用this,则this指代什么是依据运行时此函数在什么对象上被挪用。 我们还能够运用applycall两个全局要领来转变函数中this的详细指向。

1. 全局代码中的this

console.log(this === window); //true 全局范围内运用this指向window对象

2. 平常的函数挪用

function f(){
    this.name = "tony"; // this在运行时指向window对象,在严厉形式下则是undefined
}

3. 在对象中运用

var o = {
    name: "tony",
    print: function(){
        console.log(this.name);  //this指向对象o,然则能够转变其指向
    }
};

4. 作为组织函数

new F(); // 函数内部的this指向新建立的对象。

5. 多层嵌套的内部函数

var name = "global";
var person = {
    name : "person",
    hello : function(sth){
        var sayhello = function(sth) {
            console.log(this.name + " says " + sth);
        };
        sayhello(sth);
    }
}
person.hello("hello world");//global says hello world

在内部函数中,this没有按料想的绑定到外层函数对象上,而是绑定到了全局对象。这里广泛被认为是JavaScript言语的设想毛病,由于没有人想让内部函数中的this指向全局对象。平常的处理方式是将this作为变量保留下来,平常约定为that或许self:

var name = "global";
var person = {
    name : "person",
    hello : function(sth){
        var that = this;
        var sayhello = function(sth) {
            console.log(that.name + " says " + sth);
        };
        sayhello(sth);
    }
}
person.hello("hello world");//person says hello world

6. 事宜中的this

var ele = document.getElementById("id");
ele.addEventListener('click',function(){
    console.log(this);  //this指向dom元素
});

7. 运用apply和call转变this的指向

apply和call相似,只是背面的参数是经由过程一个数组传入,而不是离开传入。二者都是将某个函数绑定到某个详细对象上运用,天然此时的this会被显式的设置为第一个参数。二者的要领定义:

call( thisArg [,arg1,arg2,… ] );  // 参数列表,arg1,arg2,...
apply(thisArg [,argArray] );     // 参数数组,argArray
var name = 'global';
var o = {
    name: 'job',
    getName: function(){
        console.log(this.name);
    }
};
o.getName(); // job

//用call或apply转变函数中this的指向
o.getName.call(this); // global

简朴的总结:

  1. 当函数作为对象的要领挪用时,this指向该对象。

  2. 当函数作为淡出函数挪用时,this指向全局对象(严厉形式时,为undefined)

  3. 组织函数中的this指向新建立的对象

  4. 嵌套函数中的this不会继续上层函数的this,假如须要,能够用一个变量保留上层函数的this。

8. bind()

一个题目:

$("#ele").click = obj.handler;

假如在handler中用了this,this会绑定在obj上么?明显不是,赋值今后,函数是在回调中实行的,this会绑定到$(“#some-div”)元素上。那我们怎样能处理回调函数绑定的题目?ES5中引入了一个新的要领,bind():

fun.bind(thisArg[, arg1[, arg2[, ...]]])

thisArg
当绑定函数被挪用时,该参数会作为原函数运行时的this指向.当运用new 操纵符挪用绑定函数时,该参数无效.
arg1, arg2, ...
当绑定函数被挪用时,这些参数加上绑定函数自身的参数会根据递次作为原函数运行时的参数.

该要领建立一个新函数,称为绑定函数,绑定函数会以建立它时传入bind要领的第一个参数作为this,传入bind要领的第二个以及今后的参数加上绑定函数运行时自身的参数根据递次作为原函数的参数来挪用原函数.

$("#ele").click(person.hello.bind(person));
//响应元素被点击时,输出person says hello world

该要领也很轻易模仿,看下Prototype.js中bind要领的源码:

Function.prototype.bind = function(){
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
  return function(){
    return fn.apply(object,
      args.concat(Array.prototype.slice.call(arguments)));
  };
};

参考资料

js陈词滥调之this,constructor ,prototype

详解JavaScript中的this

    原文作者:Allin
    原文地址: https://segmentfault.com/a/1190000006110870
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞