JavaScipt对象的属性
0 36

在JavaScript中,所有的对象都是一组属性的集合,属性可以是数值,字符串等原始类型,也可以是函数,或者是其他对象。 

属性的类型

JavaScript中的属性有两种类型:数据属性和访问器属性。

数据属性

数据属性可以看成是直接封装了一个内部变量,内部变量中存放了该属性的值。 当对某个对象尚未存在的属性进行赋值时,该属性将会作为数据属性被自动创建。

var o = {};
o.prop1 = "value1";

上面的代码中,对象o的属性prop1即会在被赋值时自动创建。

数据属性也可通过Object.defineProperty方法和value定义来创建。

var o = {};
   Object.defineProperty(o,"prop1",{  value : "value1",  writable : true
}

访问器属性

访问器属性类似于C#,Ruby,Delphi等语言中的属性,内部可以不用直接关联一个数据变量,而是为属性的读取和更新分别提供了一个相应的getter方法和setter方法。 访问器属性必须通过Object.defineProperty或其他类似的方法事先进行定义。

var o = {};
Object.defineProperty(o,"prop1",{  
  get: function(){     
     if (this._prop1 === undefined) {        
         this._prop1 = 1;     
     }     
     return this._prop1;  
  },  
  set : function(s){     
    if (typeof s == "string"){        
        this._prop1 = parseFloat(s);     
    } else if ( typeof s == "number") {        
        this._prop1 = s;     
    } else {        
        throw new Error("invalie parameter!");     
    }  
  }
}

有了get方法,我们就可以在属性第一次被访问时才去进行初期化处理,而有了set方法,我们就可以追加对赋值进行类型转化等很多数据属性没法实现的程序逻辑。

属性的特性

ES5开始,JavaScript为属性提供了三个特性用于描述其各种特征。特性是内部值,不能直接访问。属性的特性会有一些默认值,要修改特性的默认值,必须使用Object.defineProperty方法。

下面依次对这些特性进行说明

configurable

configurable特性定义是否可以通过delete操作符来删除属性,默认值是true。

var o = {};
o.p1="value1";
console.log(o.p1); // value1
delete o.p1;
console.log(o.p1); // undefine

如以上代码所示,属性被通过delete操作符删除之后再去访问就已变成未定义了。 然后,我们可以把属性的Configurable特性设置为false来防止属性删除。

var o = {};
o.p1="value1";
console.log(o.p1); // value1
Object.defineProperty(o, "p1", {    configurable: false
})     delete o.p1;
console.log(o.p1); // value1

enumerable

enumerable特性定义是否能够通过for…in语句来枚举出属性,默认是true

writable

writable特性定义表示属性值是否可以修改,默认为true。

属性的继承

属性可以通过对象的原型链进行继承。

var objA = new Object();
objA.prop1 = 10;
function Func1() {}
Func1.prototype = objA;
var objB = new Func1();
function Func2() {}
Func2.prototype = objB;
var objC = new Func2();
console.log(objC.prop1);       // 10

上面的代码中,objC本身没有prop1属性,因此访问objC.prop1时,JavaScript将会按照objC—>objB—>objA的原型链进行顺序查找,最后从objA中取出该属性值。

objC.prop1 = 20;

这时如重新将objC.prop1进行赋值,并不会影响到objB和objA,而是objC自身会被自动创建一个同名的数据属性。

console.log(objC.prop1); //20
console.log(objB.prop1); //10
console.log(objA.prop1); //10

属性的键值

JavaScript里对象的属性是以键/值对的形式存在的,这里的「键」不限于字符串类型,也可以是数值或其他对象

事实上,JavaScript中的数组(Array),本质上也是一个键/值对的集合,数值类型的自然索引也是作为属性名(键)存在的。 请看以下代码:

//数值也可以是属性名(键)
var a = [0,9,2];
console.log(2 in a); // 输出:true
console.log(3 in a); // 输出:false
console.log(a.1); // 语法错
//任意对象也可以是属性名(键)
var d1 = new Date("2012/01/01"),    d2 = new Date("2013/03/01"),    o = {    }; o[d1] = "2012/01/01";
o[d2] = "2013/03/01";
console.log(o[d1]); // 2012/01/01
console.log(o[d2]); // 2013/03/01
//下面代码,d1,d2在JavaScript语法里被当作变量名的字符串处理,
console.log(o.d1);  // undefined
console.log(o.d2);  // undefined

字符串以外的值虽然也可以作为属性的键值,但因为JavasSript语法只允许字符串为变量名,所以不能以a.1或o.d1这样的方式,而只能以a[1]或o[d1]的方式访问对象的属性。

对象限制

ES5中提供了一系列限制对象被修改的方法,按限制程度由低到高,依次有禁止扩展,密封,冻结三种模式。当然,即使是冻结模式,访问器属性的set方法仍然可正常动作,表现出来就是该属性值仍可修改。

禁止扩展对象

通过Object.preventExtensions()方法可以禁止将对象进行扩展,禁止扩展后的对象无法:

  • 添加新的属性

但可以:

  • 删除已有的属性
  • 改变已有属性的特性
  • 修改已有数据属性的值(如果该属性可写)
  • 修改已有访问器属性的值(如果有set方法)

密封对象

通过Object.seal方法可以将对象进行密封,密封后的对象无法:

  • 添加新的属性
  • 删除已有的属性
  • 改变已有属性的特性

但可以

  • 修改已有数据属性的值(如果该属性可写)
  • 修改已有访问器属性的值(如果有set方法)

冻结对象

通过Object.freeze方法可以将对象进行冻结,冻结后的对象无法:

  • 添加新的属性
  • 删除已有的属性
  • 改变已有属性的特性
  • 修改已有数据属性的值(即使该属性可写)

但可以

  • 修改已有访问器属性的值(如果有set方法)

相关方法汇总

属性的相关方法都是以Object的静态方法或原型方法的形式提供的,下面简单的做一下汇总:

  • 属性定义相关
    • Object.create() 创建对象的同时定义该对象的属性
    • Object.defineProperty() 定义一个属性
    • Object.defineProperties() 定义一组属性
    • Object.getOwnPropertyDescriptor() 获取属性定义信息
  • 属性访问相关
    • Object.keys() 获取对象的所有属性名,仅限于可枚举的自身属性
    • Object.getOwnPropertyNames() 获取对象的所有属性名,包括可枚举和不可枚举,仅限自身属性
    • Object.prototype.hasOwnProperty() 判断对象自身是否拥有某个属性
  • 对象限制相关
    • Object.preventExtensions() 限制对象扩展
    • Object.isExtensible() 判断对象是否可以扩展
    • Object.seal() 密封对象
    • Object.isSealed() 判断对象是否被密封
    • Object.freeze() 冻结对象
    • Object.isFrozen() 判断对象是否被冻结
0 36
() 全部评论
所有回复 (0)

热门

最新

  • Web3D编程 2 0 1 发布

    点击查看例子

    代码效果


    源码

    <!DOCTYPE html> <html> <head> <title>材质和光源</title> <script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script> <script type="text/javascript" src="../libs/dat.gui.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <!-- Div which will hold the Output --> <div id="LapBin-output"> </div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> // 加载所有内容后,我们将运行Three.js function init() { // 创建一个场景,该场景将包含所有元素,例如对象、摄影机和灯光。 var scene = new THREE.Scene(); // 创建一个摄像头,它定义了我们要看的范围。 var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.2, 1000); // 创建渲染并设置大小 var renderer = new THREE.WebGLRenderer(); renderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0)); renderer.setSize(window.innerWidth, window.innerHeight); renderer.shadowMapEnabled = true; // 创建平面 var planeGeometry = new THREE.PlaneGeometry(60, 30); var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff}); var plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.receiveShadow = true; // 旋转并定位平面 plane.rotation.x = -0.5 * Math.PI; plane.position.x = 10; plane.position.y = 0; plane.position.z = -10; // 将平面添加到场景中 scene.add(plane); // 创建一个立方体 var cubeGeometry = new THREE.BoxGeometry(4, 4, 4); var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000}); var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); cube.castShadow = true; // 定位立方体 cube.position.x = -4; cube.position.y = 3; cube.position.z = -10; // 将立方体添加到场景中 scene.add(cube); // 创建一个球体 var sphereGeometry = new THREE.SphereGeometry(4, 20, 20); var sphereMaterial = new THREE.MeshLambertMaterial({color: 0xdd77ff}); var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); // 定位球体 sphere.position.x = 20; sphere.position.y = 4; sphere.position.z = -10; sphere.castShadow = true; // 将球体添加到场景中 scene.add(sphere); // 将摄影机定位并指向场景的中心 camera.position.x = -30; camera.position.y = 40; camera.position.z = 30; camera.lookAt(scene.position); // 为阴影添加聚光灯 var spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(-40, 60, -10); spotLight.castShadow = true; scene.add(spotLight); // 将渲染器的输出添加到html元素 document.getElementById("LapBin-output").appendChild(renderer.domElement); // 渲染场景 renderer.render(scene, camera); } window.onload = init; </script> </body> </html>
  • LapBin(ThreeJS) 6 0 1 发布
  • 点击查看例子

    代码效果




    天空盒使用源码

    <!DOCTYPE html> <html lang="en">     <head>         <title>three.js - skybox</title>         <meta charset="utf-8">         <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">         <link type="text/css" rel="stylesheet" href="main.css">     </head>     <body>         <div id="container"></div>         <script type="module">             import * as THREE from '../build/three.module.js';             import { OrbitControls } from './jsm/controls/OrbitControls.js';             var scene, camera , renderer;             init();             animate();             function init() {                 // scene                 scene = new THREE.Scene();                 // camera                 camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 200 );                 camera.position.set( - 15, 7, 15 );                 camera.lookAt( scene.position );                              // skybox                 var cubeTextureLoader = new THREE.CubeTextureLoader();                 cubeTextureLoader.setPath( 'textures/cube/Park2/' ); //天空盒图片文件路径                 var cubeTexture = new THREE.CubeTextureLoader.load( [                     "posx.jpg", "negx.jpg", //图片 http://www.cglap.com/assets/lapbin/textures/cube/Park2/negx.jpg                     "posy.jpg", "negy.jpg", // http://www.cglap.com/assets/lapbin/textures/cube/Park2/negy.jpg                     "posz.jpg", "negz.jpg" //http://www.cglap.com/assets/lapbin/textures/cube/Park2/negz.jpg                 ] );                 scene.background = cubeTexture;                 // light                 var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );                 scene.add( ambientLight );                 var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.6 );                 directionalLight.position.set( - 1, 1, 1 );                 scene.add( directionalLight );                 // renderer                 renderer = new THREE.WebGLRenderer( { antialias: true } );                 renderer.setSize( window.innerWidth, window.innerHeight );                 renderer.setPixelRatio( window.devicePixelRatio );                 document.body.appendChild( renderer.domElement );                 // 鼠标控制旋转                 var controls = new OrbitControls( camera, renderer.domElement );                 controls.minDistance = 5;                 controls.maxDistance = 50;                              //                 window.addEventListener( 'resize', onResize, false );             }             function onResize() {                 camera.aspect = window.innerWidth / window.innerHeight;                 camera.updateProjectionMatrix();                 renderer.setSize( window.innerWidth, window.innerHeight );             }             function animate() {                 requestAnimationFrame( animate );                 render();             }             function render() {                 renderer.render( scene, camera );             }         </script> </body> </html>
  • 例子查看链接gui

    为了能够快速地搭建three.js的交互ui,官方提供了一个GUI组件,通过简单的语法学习就能够使用。

    下面我们就来学习如何使用

    用法一

    首先声明一个对象,这个对象设置获取一个交互.

       var params = {                 color: '#ffffff',                 scale: 4,                 flowX: 1,                 flowY: 1 , states:"Walking"             };

    然后就就可以使用GUI来进行生成交互UI组件

    生成一个panel组件版,然后将组件的对象添加到这个组件版,完成之后就能够生成一个交互界面了。

     // dat.gui

    颜色选择器                var gui = new GUI();                 gui.addColor( params, 'color' ).onChange( function ( value ) {                    // do something                 } );


    拉动条
    不仅可以生成按钮,也可以生成拉动条。 gui.add( params, 'scale', 1, 10 ).onChange( function ( value ) { // do something  } );


    gui.add( params, 'flowX', - 1, 1 ).step( 0.01 ).onChange( function ( value ) {                   // do something } );


     gui.add( params, 'flowY', - 1, 1 ).step( 0.01 ).onChange( function ( value ) {                   // do something                 } );


    下拉表
     //选项 var states = [ 'Idle', 'Walking', 'Running', 'Dance', 'Death', 'Sitting', 'Standing' ];  // 添加  gui.add( params, 'states' ).options( states ).onChange( function ( value ) {              // do something } );
    效果图


    全部代码

    <!DOCTYPE html> <html lang="en">     <head>         <title>three.js - gui</title>         <meta charset="utf-8">         <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">         <link type="text/css" rel="stylesheet" href="main.css">     </head>     <body>         <div id="container"></div>         <script type="module">             import * as THREE from '../build/three.module.js';             import { GUI } from './jsm/libs/dat.gui.module.js';             var scene, camera, renderer;             var params = {                 color: '#ffffff',                 scale: 4,                 flowX: 1,                 flowY: 1,                 states:"Walking"             };             init();             animate();             function init() {                 // scene                 scene = new THREE.Scene();                 // camera                 camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 200 );                 camera.position.set( - 15, 7, 15 );                 camera.lookAt( scene.position );                 // renderer                 renderer = new THREE.WebGLRenderer( { antialias: true } );                 renderer.setSize( window.innerWidth, window.innerHeight );                 renderer.setPixelRatio( window.devicePixelRatio );                 document.body.appendChild( renderer.domElement );                 // dat.gui                 var gui = new GUI();                 gui.addColor( params, 'color' ).onChange( function ( value ) {                     //do something                 } );                 gui.add( params, 'scale', 1, 10 ).onChange( function ( value ) {                     //do something                 } );                 gui.add( params, 'flowX', - 1, 1 ).step( 0.01 ).onChange( function ( value ) {                     //do something                 } );                 gui.add( params, 'flowY', - 1, 1 ).step( 0.01 ).onChange( function ( value ) {                     //do something                 } );                 //选项                 var states = [ 'Idle', 'Walking', 'Running', 'Dance', 'Death', 'Sitting', 'Standing' ];                  gui.add( params, 'states' ).options( states ).onChange( function ( value ) { //do something                 } );;                              gui.open();                 window.addEventListener( 'resize', onResize, false );             }             function onResize() {                 camera.aspect = window.innerWidth / window.innerHeight;                 camera.updateProjectionMatrix();                 renderer.setSize( window.innerWidth, window.innerHeight );             }             function animate() {                 requestAnimationFrame( animate );                 render();             }             function render() {                 renderer.render( scene, camera );             }         </script> </body> </html>
  • LapBin(ThreeJS) 12 0 1 发布